Completed
Branch FET-3467-waitlists (4406f2)
by
unknown
46:31 queued 34:26
created
modules/event_single/EED_Event_Single.module.php 1 patch
Indentation   +462 added lines, -462 removed lines patch added patch discarded remove patch
@@ -13,467 +13,467 @@  discard block
 block discarded – undo
13 13
 class EED_Event_Single extends EED_Module
14 14
 {
15 15
 
16
-    const EVENT_DETAILS_PRIORITY = 100;
17
-    const EVENT_DATETIMES_PRIORITY = 110;
18
-    const EVENT_TICKETS_PRIORITY = 120;
19
-    const EVENT_VENUES_PRIORITY = 130;
20
-
21
-    /**
22
-     * @type bool $using_get_the_excerpt
23
-     */
24
-    protected static $using_get_the_excerpt = false;
25
-
26
-
27
-    /**
28
-     * @type EE_Template_Part_Manager $template_parts
29
-     */
30
-    protected $template_parts;
31
-
32
-
33
-    /**
34
-     * @return EED_Module|EED_Event_Single
35
-     */
36
-    public static function instance()
37
-    {
38
-        return parent::get_instance(__CLASS__);
39
-    }
40
-
41
-
42
-    /**
43
-     * set_hooks - for hooking into EE Core, other modules, etc
44
-     *
45
-     * @return    void
46
-     */
47
-    public static function set_hooks()
48
-    {
49
-        add_filter('FHEE_run_EE_wp', '__return_true');
50
-        add_action('wp_loaded', array('EED_Event_Single', 'set_definitions'), 2);
51
-        $custom_post_types = EE_Register_CPTs::get_CPTs();
52
-        EE_Config::register_route(
53
-            $custom_post_types['espresso_events']['singular_slug'],
54
-            'Event_Single',
55
-            'run'
56
-        );
57
-    }
58
-
59
-    /**
60
-     * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
61
-     *
62
-     * @return    void
63
-     */
64
-    public static function set_hooks_admin()
65
-    {
66
-        add_action('wp_loaded', array('EED_Event_Single', 'set_definitions'), 2);
67
-    }
68
-
69
-
70
-    /**
71
-     * set_definitions
72
-     *
73
-     * @static
74
-     * @return void
75
-     */
76
-    public static function set_definitions()
77
-    {
78
-        define('EVENT_SINGLE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets' . DS);
79
-        define('EVENT_SINGLE_TEMPLATES_PATH', plugin_dir_path(__FILE__) . 'templates' . DS);
80
-    }
81
-
82
-
83
-    /**
84
-     * set_config
85
-     *
86
-     * @void
87
-     */
88
-    protected function set_config()
89
-    {
90
-        $this->set_config_section('template_settings');
91
-        $this->set_config_class('EE_Event_Single_Config');
92
-        $this->set_config_name('EED_Event_Single');
93
-    }
94
-
95
-
96
-    /**
97
-     * initialize_template_parts
98
-     *
99
-     * @param EE_Config_Base|EE_Event_Single_Config $config
100
-     * @return EE_Template_Part_Manager
101
-     */
102
-    public function initialize_template_parts(EE_Event_Single_Config $config = null)
103
-    {
104
-        /** @type EE_Event_Single_Config $config */
105
-        $config = $config instanceof EE_Event_Single_Config ? $config : $this->config();
106
-        EEH_Autoloader::instance()->register_template_part_autoloaders();
107
-        $template_parts = new EE_Template_Part_Manager();
108
-        $template_parts->add_template_part(
109
-            'tickets',
110
-            __('Ticket Selector', 'event_espresso'),
111
-            'content-espresso_events-tickets.php',
112
-            $config->display_order_tickets
113
-        );
114
-        $template_parts->add_template_part(
115
-            'datetimes',
116
-            __('Dates and Times', 'event_espresso'),
117
-            'content-espresso_events-datetimes.php',
118
-            $config->display_order_datetimes
119
-        );
120
-        $template_parts->add_template_part(
121
-            'event',
122
-            __('Event Description', 'event_espresso'),
123
-            'content-espresso_events-details.php',
124
-            $config->display_order_event
125
-        );
126
-        $template_parts->add_template_part(
127
-            'venue',
128
-            __('Venue Information', 'event_espresso'),
129
-            'content-espresso_events-venues.php',
130
-            $config->display_order_venue
131
-        );
132
-        do_action('AHEE__EED_Event_Single__initialize_template_parts', $template_parts);
133
-        return $template_parts;
134
-    }
135
-
136
-
137
-    /**
138
-     * run - initial module setup
139
-     *
140
-     * @param WP $WP
141
-     * @return    void
142
-     */
143
-    public function run($WP)
144
-    {
145
-        // ensure valid EE_Events_Single_Config() object exists
146
-        $this->set_config();
147
-        // check what template is loaded
148
-        add_filter('template_include', array($this, 'template_include'), 999, 1);
149
-        add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
150
-        // load css
151
-        add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
152
-    }
153
-
154
-
155
-    /**
156
-     * template_include
157
-     *
158
-     * @param    string $template
159
-     * @return    string
160
-     */
161
-    public function template_include($template)
162
-    {
163
-        global $post;
164
-        /** @type EE_Event_Single_Config $config */
165
-        $config = $this->config();
166
-        if ($config->display_status_banner_single) {
167
-            add_filter('the_title', array('EED_Event_Single', 'the_title'), 100, 2);
168
-        }
169
-        // not a custom template?
170
-        if (
171
-            !post_password_required($post)
172
-            && (
173
-                apply_filters('FHEE__EED_Event_Single__template_include__allow_custom_selected_template', false)
174
-                || EE_Registry::instance()
175
-                    ->load_core('Front_Controller')
176
-                    ->get_selected_template() !== 'single-espresso_events.php'
177
-            )
178
-
179
-        ) {
180
-            EEH_Template::load_espresso_theme_functions();
181
-            // then add extra event data via hooks
182
-            add_action('loop_start', array('EED_Event_Single', 'loop_start'));
183
-            add_filter('get_the_excerpt', array('EED_Event_Single', 'get_the_excerpt'), 1, 1);
184
-            add_filter(
185
-                'the_content',
186
-                array('EED_Event_Single', 'event_details'),
187
-                EED_Event_Single::EVENT_DETAILS_PRIORITY
188
-            );
189
-            add_action('loop_end', array('EED_Event_Single', 'loop_end'));
190
-            // don't display entry meta because the existing theme will take car of that
191
-            add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
192
-        }
193
-        return $template;
194
-    }
195
-
196
-
197
-    /**
198
-     * loop_start
199
-     *
200
-     * @param    array $wp_query_array an array containing the WP_Query object
201
-     * @return    void
202
-     */
203
-    public static function loop_start($wp_query_array)
204
-    {
205
-        global $post;
206
-        do_action('AHEE_event_details_before_post', $post, $wp_query_array);
207
-    }
208
-
209
-
210
-    /**
211
-     * the_title
212
-     *
213
-     * @param    string $title
214
-     * @param    int $id
215
-     * @return    string
216
-     */
217
-    public static function the_title($title = '', $id = 0)
218
-    {
219
-        global $post;
220
-        return in_the_loop() && $post->ID === (int)$id
221
-            ? espresso_event_status_banner($post->ID) . $title
222
-            : $title;
223
-    }
224
-
225
-
226
-    /**
227
-     * get_the_excerpt
228
-     * kinda hacky, but if a theme is using get_the_excerpt(),
229
-     * then we need to remove our filters on the_content()
230
-     *
231
-     * @param        string $excerpt
232
-     * @return        string
233
-     */
234
-    public static function get_the_excerpt($excerpt = '')
235
-    {
236
-        EED_Event_Single::$using_get_the_excerpt = true;
237
-        add_filter('wp_trim_excerpt', array('EED_Event_Single', 'end_get_the_excerpt'), 999, 1);
238
-        return $excerpt;
239
-    }
240
-
241
-
242
-    /**
243
-     * end_get_the_excerpt
244
-     *
245
-     * @param  string $text
246
-     * @return string
247
-     */
248
-    public static function end_get_the_excerpt($text = '')
249
-    {
250
-        EED_Event_Single::$using_get_the_excerpt = false;
251
-        return $text;
252
-    }
253
-
254
-
255
-    /**
256
-     * event_details
257
-     *
258
-     * @param    string $content
259
-     * @return    string
260
-     */
261
-    public static function event_details($content)
262
-    {
263
-        global $post;
264
-        static $current_post_ID = 0;
265
-        if (
266
-            $current_post_ID !== $post->ID
267
-            && $post->post_type === 'espresso_events'
268
-            && !EED_Event_Single::$using_get_the_excerpt
269
-            && !post_password_required()
270
-        ) {
271
-            // Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
272
-            // Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
273
-            // BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
274
-            // We want to allow those plugins to still do their thing and have access to our content, but depending on
275
-            // how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
276
-            // so the following allows this filter to be applied multiple times, but only once for real
277
-            $current_post_ID = did_action('loop_start') ? $post->ID : 0;
278
-            if (EE_Registry::instance()->CFG->template_settings->EED_Event_Single->use_sortable_display_order) {
279
-                // we need to first remove this callback from being applied to the_content()
280
-                // (otherwise it will recurse and blow up the interweb)
281
-                remove_filter(
282
-                    'the_content',
283
-                    array('EED_Event_Single', 'event_details'),
284
-                    EED_Event_Single::EVENT_DETAILS_PRIORITY
285
-                );
286
-                EED_Event_Single::instance()->template_parts = EED_Event_Single::instance()->initialize_template_parts();
287
-                $content = EEH_Template::locate_template('content-espresso_events-details.php');
288
-                $content = EED_Event_Single::instance()->template_parts->apply_template_part_filters($content);
289
-                add_filter(
290
-                    'the_content',
291
-                    array('EED_Event_Single', 'event_details'),
292
-                    EED_Event_Single::EVENT_DETAILS_PRIORITY
293
-                );
294
-            } else {
295
-                $content = EED_Event_Single::use_filterable_display_order();
296
-            }
297
-        }
298
-        return $content;
299
-    }
300
-
301
-
302
-    /**
303
-     * use_filterable_display_order
304
-     *
305
-     * @return string
306
-     */
307
-    protected static function use_filterable_display_order()
308
-    {
309
-        // since the 'content-espresso_events-details.php' template might be used directly from within a theme,
310
-        // it uses the_content() for displaying the $post->post_content
311
-        // so in order to load a template that uses the_content()
312
-        // from within a callback being used to filter the_content(),
313
-        // we need to first remove this callback from being applied to the_content()
314
-        // (otherwise it will recurse and blow up the interweb)
315
-        remove_filter(
316
-            'the_content',
317
-            array('EED_Event_Single', 'event_details'),
318
-            EED_Event_Single::EVENT_DETAILS_PRIORITY
319
-        );
320
-        //now add additional content
321
-        add_filter(
322
-            'the_content',
323
-            array('EED_Event_Single', 'event_datetimes'),
324
-            EED_Event_Single::EVENT_DATETIMES_PRIORITY,
325
-            1
326
-        );
327
-        add_filter(
328
-            'the_content',
329
-            array('EED_Event_Single', 'event_tickets'),
330
-            EED_Event_Single::EVENT_TICKETS_PRIORITY,
331
-            1
332
-        );
333
-        add_filter(
334
-            'the_content',
335
-            array('EED_Event_Single', 'event_venues'),
336
-            EED_Event_Single::EVENT_VENUES_PRIORITY,
337
-            1
338
-        );
339
-        do_action('AHEE__EED_Event_Single__use_filterable_display_order__after_add_filters');
340
-        // now load our template
341
-        $content = EEH_Template::locate_template('content-espresso_events-details.php');
342
-        //now add our filter back in, plus some others
343
-        add_filter(
344
-            'the_content',
345
-            array('EED_Event_Single', 'event_details'),
346
-            EED_Event_Single::EVENT_DETAILS_PRIORITY
347
-        );
348
-        remove_filter(
349
-            'the_content',
350
-            array('EED_Event_Single', 'event_datetimes'),
351
-            EED_Event_Single::EVENT_DATETIMES_PRIORITY
352
-        );
353
-        remove_filter(
354
-            'the_content',
355
-            array('EED_Event_Single', 'event_tickets'),
356
-            EED_Event_Single::EVENT_TICKETS_PRIORITY
357
-        );
358
-        remove_filter(
359
-            'the_content',
360
-            array('EED_Event_Single', 'event_venues'),
361
-            EED_Event_Single::EVENT_VENUES_PRIORITY
362
-        );
363
-        do_action('AHEE__EED_Event_Single__use_filterable_display_order__after_remove_filters');
364
-        // we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
365
-        return $content;
366
-    }
367
-
368
-
369
-    /**
370
-     * event_datetimes - adds datetimes ABOVE content
371
-     *
372
-     * @param        string $content
373
-     * @return        string
374
-     */
375
-    public static function event_datetimes($content)
376
-    {
377
-        return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
378
-    }
379
-
380
-
381
-    /**
382
-     * event_tickets - adds tickets ABOVE content (which includes datetimes)
383
-     *
384
-     * @param        string $content
385
-     * @return        string
386
-     */
387
-    public static function event_tickets($content)
388
-    {
389
-        return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
390
-    }
391
-
392
-
393
-    /**
394
-     * event_venues
395
-     *
396
-     * @param    string $content
397
-     * @return    string
398
-     */
399
-    public static function event_venue($content)
400
-    {
401
-        return EED_Event_Single::event_venues($content);
402
-    }
403
-
404
-
405
-    /**
406
-     * event_venues - adds venues BELOW content
407
-     *
408
-     * @param        string $content
409
-     * @return        string
410
-     */
411
-    public static function event_venues($content)
412
-    {
413
-        return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
414
-    }
415
-
416
-
417
-    /**
418
-     * loop_end
419
-     *
420
-     * @param        array $wp_query_array an array containing the WP_Query object
421
-     * @return        void
422
-     */
423
-    public static function loop_end($wp_query_array)
424
-    {
425
-        global $post;
426
-        do_action('AHEE_event_details_after_post', $post, $wp_query_array);
427
-    }
428
-
429
-
430
-    /**
431
-     * wp_enqueue_scripts
432
-     *
433
-     * @return    void
434
-     */
435
-    public function wp_enqueue_scripts()
436
-    {
437
-        // get some style
438
-        if (
439
-            apply_filters('FHEE_enable_default_espresso_css', TRUE)
440
-            && apply_filters('FHEE__EED_Event_Single__wp_enqueue_scripts__enable_css', TRUE)
441
-        ) {
442
-            // first check uploads folder
443
-            if (is_readable(get_stylesheet_directory() . $this->theme . DS . 'style.css')) {
444
-                wp_register_style(
445
-                    $this->theme,
446
-                    get_stylesheet_directory_uri() . $this->theme . DS . 'style.css',
447
-                    array('dashicons', 'espresso_default')
448
-                );
449
-            } else {
450
-                wp_register_style(
451
-                    $this->theme,
452
-                    EE_TEMPLATES_URL . $this->theme . DS . 'style.css',
453
-                    array('dashicons', 'espresso_default')
454
-                );
455
-            }
456
-            wp_enqueue_script($this->theme);
457
-            if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
458
-                add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
459
-            }
460
-        }
461
-    }
462
-
463
-
464
-    /**
465
-     * display_venue
466
-     *
467
-     * @return    bool
468
-     */
469
-    public static function display_venue()
470
-    {
471
-        /** @type EE_Event_Single_Config $config */
472
-        $config = EED_Event_Single::instance()->config();
473
-        $display_venue = $config->display_venue === null ? true : $config->display_venue;
474
-        $venue_name = EEH_Venue_View::venue_name();
475
-        return $display_venue && !empty($venue_name);
476
-    }
16
+	const EVENT_DETAILS_PRIORITY = 100;
17
+	const EVENT_DATETIMES_PRIORITY = 110;
18
+	const EVENT_TICKETS_PRIORITY = 120;
19
+	const EVENT_VENUES_PRIORITY = 130;
20
+
21
+	/**
22
+	 * @type bool $using_get_the_excerpt
23
+	 */
24
+	protected static $using_get_the_excerpt = false;
25
+
26
+
27
+	/**
28
+	 * @type EE_Template_Part_Manager $template_parts
29
+	 */
30
+	protected $template_parts;
31
+
32
+
33
+	/**
34
+	 * @return EED_Module|EED_Event_Single
35
+	 */
36
+	public static function instance()
37
+	{
38
+		return parent::get_instance(__CLASS__);
39
+	}
40
+
41
+
42
+	/**
43
+	 * set_hooks - for hooking into EE Core, other modules, etc
44
+	 *
45
+	 * @return    void
46
+	 */
47
+	public static function set_hooks()
48
+	{
49
+		add_filter('FHEE_run_EE_wp', '__return_true');
50
+		add_action('wp_loaded', array('EED_Event_Single', 'set_definitions'), 2);
51
+		$custom_post_types = EE_Register_CPTs::get_CPTs();
52
+		EE_Config::register_route(
53
+			$custom_post_types['espresso_events']['singular_slug'],
54
+			'Event_Single',
55
+			'run'
56
+		);
57
+	}
58
+
59
+	/**
60
+	 * set_hooks_admin - for hooking into EE Admin Core, other modules, etc
61
+	 *
62
+	 * @return    void
63
+	 */
64
+	public static function set_hooks_admin()
65
+	{
66
+		add_action('wp_loaded', array('EED_Event_Single', 'set_definitions'), 2);
67
+	}
68
+
69
+
70
+	/**
71
+	 * set_definitions
72
+	 *
73
+	 * @static
74
+	 * @return void
75
+	 */
76
+	public static function set_definitions()
77
+	{
78
+		define('EVENT_SINGLE_ASSETS_URL', plugin_dir_url(__FILE__) . 'assets' . DS);
79
+		define('EVENT_SINGLE_TEMPLATES_PATH', plugin_dir_path(__FILE__) . 'templates' . DS);
80
+	}
81
+
82
+
83
+	/**
84
+	 * set_config
85
+	 *
86
+	 * @void
87
+	 */
88
+	protected function set_config()
89
+	{
90
+		$this->set_config_section('template_settings');
91
+		$this->set_config_class('EE_Event_Single_Config');
92
+		$this->set_config_name('EED_Event_Single');
93
+	}
94
+
95
+
96
+	/**
97
+	 * initialize_template_parts
98
+	 *
99
+	 * @param EE_Config_Base|EE_Event_Single_Config $config
100
+	 * @return EE_Template_Part_Manager
101
+	 */
102
+	public function initialize_template_parts(EE_Event_Single_Config $config = null)
103
+	{
104
+		/** @type EE_Event_Single_Config $config */
105
+		$config = $config instanceof EE_Event_Single_Config ? $config : $this->config();
106
+		EEH_Autoloader::instance()->register_template_part_autoloaders();
107
+		$template_parts = new EE_Template_Part_Manager();
108
+		$template_parts->add_template_part(
109
+			'tickets',
110
+			__('Ticket Selector', 'event_espresso'),
111
+			'content-espresso_events-tickets.php',
112
+			$config->display_order_tickets
113
+		);
114
+		$template_parts->add_template_part(
115
+			'datetimes',
116
+			__('Dates and Times', 'event_espresso'),
117
+			'content-espresso_events-datetimes.php',
118
+			$config->display_order_datetimes
119
+		);
120
+		$template_parts->add_template_part(
121
+			'event',
122
+			__('Event Description', 'event_espresso'),
123
+			'content-espresso_events-details.php',
124
+			$config->display_order_event
125
+		);
126
+		$template_parts->add_template_part(
127
+			'venue',
128
+			__('Venue Information', 'event_espresso'),
129
+			'content-espresso_events-venues.php',
130
+			$config->display_order_venue
131
+		);
132
+		do_action('AHEE__EED_Event_Single__initialize_template_parts', $template_parts);
133
+		return $template_parts;
134
+	}
135
+
136
+
137
+	/**
138
+	 * run - initial module setup
139
+	 *
140
+	 * @param WP $WP
141
+	 * @return    void
142
+	 */
143
+	public function run($WP)
144
+	{
145
+		// ensure valid EE_Events_Single_Config() object exists
146
+		$this->set_config();
147
+		// check what template is loaded
148
+		add_filter('template_include', array($this, 'template_include'), 999, 1);
149
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
150
+		// load css
151
+		add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
152
+	}
153
+
154
+
155
+	/**
156
+	 * template_include
157
+	 *
158
+	 * @param    string $template
159
+	 * @return    string
160
+	 */
161
+	public function template_include($template)
162
+	{
163
+		global $post;
164
+		/** @type EE_Event_Single_Config $config */
165
+		$config = $this->config();
166
+		if ($config->display_status_banner_single) {
167
+			add_filter('the_title', array('EED_Event_Single', 'the_title'), 100, 2);
168
+		}
169
+		// not a custom template?
170
+		if (
171
+			!post_password_required($post)
172
+			&& (
173
+				apply_filters('FHEE__EED_Event_Single__template_include__allow_custom_selected_template', false)
174
+				|| EE_Registry::instance()
175
+					->load_core('Front_Controller')
176
+					->get_selected_template() !== 'single-espresso_events.php'
177
+			)
178
+
179
+		) {
180
+			EEH_Template::load_espresso_theme_functions();
181
+			// then add extra event data via hooks
182
+			add_action('loop_start', array('EED_Event_Single', 'loop_start'));
183
+			add_filter('get_the_excerpt', array('EED_Event_Single', 'get_the_excerpt'), 1, 1);
184
+			add_filter(
185
+				'the_content',
186
+				array('EED_Event_Single', 'event_details'),
187
+				EED_Event_Single::EVENT_DETAILS_PRIORITY
188
+			);
189
+			add_action('loop_end', array('EED_Event_Single', 'loop_end'));
190
+			// don't display entry meta because the existing theme will take car of that
191
+			add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
192
+		}
193
+		return $template;
194
+	}
195
+
196
+
197
+	/**
198
+	 * loop_start
199
+	 *
200
+	 * @param    array $wp_query_array an array containing the WP_Query object
201
+	 * @return    void
202
+	 */
203
+	public static function loop_start($wp_query_array)
204
+	{
205
+		global $post;
206
+		do_action('AHEE_event_details_before_post', $post, $wp_query_array);
207
+	}
208
+
209
+
210
+	/**
211
+	 * the_title
212
+	 *
213
+	 * @param    string $title
214
+	 * @param    int $id
215
+	 * @return    string
216
+	 */
217
+	public static function the_title($title = '', $id = 0)
218
+	{
219
+		global $post;
220
+		return in_the_loop() && $post->ID === (int)$id
221
+			? espresso_event_status_banner($post->ID) . $title
222
+			: $title;
223
+	}
224
+
225
+
226
+	/**
227
+	 * get_the_excerpt
228
+	 * kinda hacky, but if a theme is using get_the_excerpt(),
229
+	 * then we need to remove our filters on the_content()
230
+	 *
231
+	 * @param        string $excerpt
232
+	 * @return        string
233
+	 */
234
+	public static function get_the_excerpt($excerpt = '')
235
+	{
236
+		EED_Event_Single::$using_get_the_excerpt = true;
237
+		add_filter('wp_trim_excerpt', array('EED_Event_Single', 'end_get_the_excerpt'), 999, 1);
238
+		return $excerpt;
239
+	}
240
+
241
+
242
+	/**
243
+	 * end_get_the_excerpt
244
+	 *
245
+	 * @param  string $text
246
+	 * @return string
247
+	 */
248
+	public static function end_get_the_excerpt($text = '')
249
+	{
250
+		EED_Event_Single::$using_get_the_excerpt = false;
251
+		return $text;
252
+	}
253
+
254
+
255
+	/**
256
+	 * event_details
257
+	 *
258
+	 * @param    string $content
259
+	 * @return    string
260
+	 */
261
+	public static function event_details($content)
262
+	{
263
+		global $post;
264
+		static $current_post_ID = 0;
265
+		if (
266
+			$current_post_ID !== $post->ID
267
+			&& $post->post_type === 'espresso_events'
268
+			&& !EED_Event_Single::$using_get_the_excerpt
269
+			&& !post_password_required()
270
+		) {
271
+			// Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
272
+			// Reason being is that some plugins, like Yoast, need to run through a copy of the loop early
273
+			// BEFORE headers are sent in order to examine the post content and generate content for the HTML header.
274
+			// We want to allow those plugins to still do their thing and have access to our content, but depending on
275
+			// how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
276
+			// so the following allows this filter to be applied multiple times, but only once for real
277
+			$current_post_ID = did_action('loop_start') ? $post->ID : 0;
278
+			if (EE_Registry::instance()->CFG->template_settings->EED_Event_Single->use_sortable_display_order) {
279
+				// we need to first remove this callback from being applied to the_content()
280
+				// (otherwise it will recurse and blow up the interweb)
281
+				remove_filter(
282
+					'the_content',
283
+					array('EED_Event_Single', 'event_details'),
284
+					EED_Event_Single::EVENT_DETAILS_PRIORITY
285
+				);
286
+				EED_Event_Single::instance()->template_parts = EED_Event_Single::instance()->initialize_template_parts();
287
+				$content = EEH_Template::locate_template('content-espresso_events-details.php');
288
+				$content = EED_Event_Single::instance()->template_parts->apply_template_part_filters($content);
289
+				add_filter(
290
+					'the_content',
291
+					array('EED_Event_Single', 'event_details'),
292
+					EED_Event_Single::EVENT_DETAILS_PRIORITY
293
+				);
294
+			} else {
295
+				$content = EED_Event_Single::use_filterable_display_order();
296
+			}
297
+		}
298
+		return $content;
299
+	}
300
+
301
+
302
+	/**
303
+	 * use_filterable_display_order
304
+	 *
305
+	 * @return string
306
+	 */
307
+	protected static function use_filterable_display_order()
308
+	{
309
+		// since the 'content-espresso_events-details.php' template might be used directly from within a theme,
310
+		// it uses the_content() for displaying the $post->post_content
311
+		// so in order to load a template that uses the_content()
312
+		// from within a callback being used to filter the_content(),
313
+		// we need to first remove this callback from being applied to the_content()
314
+		// (otherwise it will recurse and blow up the interweb)
315
+		remove_filter(
316
+			'the_content',
317
+			array('EED_Event_Single', 'event_details'),
318
+			EED_Event_Single::EVENT_DETAILS_PRIORITY
319
+		);
320
+		//now add additional content
321
+		add_filter(
322
+			'the_content',
323
+			array('EED_Event_Single', 'event_datetimes'),
324
+			EED_Event_Single::EVENT_DATETIMES_PRIORITY,
325
+			1
326
+		);
327
+		add_filter(
328
+			'the_content',
329
+			array('EED_Event_Single', 'event_tickets'),
330
+			EED_Event_Single::EVENT_TICKETS_PRIORITY,
331
+			1
332
+		);
333
+		add_filter(
334
+			'the_content',
335
+			array('EED_Event_Single', 'event_venues'),
336
+			EED_Event_Single::EVENT_VENUES_PRIORITY,
337
+			1
338
+		);
339
+		do_action('AHEE__EED_Event_Single__use_filterable_display_order__after_add_filters');
340
+		// now load our template
341
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
342
+		//now add our filter back in, plus some others
343
+		add_filter(
344
+			'the_content',
345
+			array('EED_Event_Single', 'event_details'),
346
+			EED_Event_Single::EVENT_DETAILS_PRIORITY
347
+		);
348
+		remove_filter(
349
+			'the_content',
350
+			array('EED_Event_Single', 'event_datetimes'),
351
+			EED_Event_Single::EVENT_DATETIMES_PRIORITY
352
+		);
353
+		remove_filter(
354
+			'the_content',
355
+			array('EED_Event_Single', 'event_tickets'),
356
+			EED_Event_Single::EVENT_TICKETS_PRIORITY
357
+		);
358
+		remove_filter(
359
+			'the_content',
360
+			array('EED_Event_Single', 'event_venues'),
361
+			EED_Event_Single::EVENT_VENUES_PRIORITY
362
+		);
363
+		do_action('AHEE__EED_Event_Single__use_filterable_display_order__after_remove_filters');
364
+		// we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
365
+		return $content;
366
+	}
367
+
368
+
369
+	/**
370
+	 * event_datetimes - adds datetimes ABOVE content
371
+	 *
372
+	 * @param        string $content
373
+	 * @return        string
374
+	 */
375
+	public static function event_datetimes($content)
376
+	{
377
+		return EEH_Template::locate_template('content-espresso_events-datetimes.php') . $content;
378
+	}
379
+
380
+
381
+	/**
382
+	 * event_tickets - adds tickets ABOVE content (which includes datetimes)
383
+	 *
384
+	 * @param        string $content
385
+	 * @return        string
386
+	 */
387
+	public static function event_tickets($content)
388
+	{
389
+		return EEH_Template::locate_template('content-espresso_events-tickets.php') . $content;
390
+	}
391
+
392
+
393
+	/**
394
+	 * event_venues
395
+	 *
396
+	 * @param    string $content
397
+	 * @return    string
398
+	 */
399
+	public static function event_venue($content)
400
+	{
401
+		return EED_Event_Single::event_venues($content);
402
+	}
403
+
404
+
405
+	/**
406
+	 * event_venues - adds venues BELOW content
407
+	 *
408
+	 * @param        string $content
409
+	 * @return        string
410
+	 */
411
+	public static function event_venues($content)
412
+	{
413
+		return $content . EEH_Template::locate_template('content-espresso_events-venues.php');
414
+	}
415
+
416
+
417
+	/**
418
+	 * loop_end
419
+	 *
420
+	 * @param        array $wp_query_array an array containing the WP_Query object
421
+	 * @return        void
422
+	 */
423
+	public static function loop_end($wp_query_array)
424
+	{
425
+		global $post;
426
+		do_action('AHEE_event_details_after_post', $post, $wp_query_array);
427
+	}
428
+
429
+
430
+	/**
431
+	 * wp_enqueue_scripts
432
+	 *
433
+	 * @return    void
434
+	 */
435
+	public function wp_enqueue_scripts()
436
+	{
437
+		// get some style
438
+		if (
439
+			apply_filters('FHEE_enable_default_espresso_css', TRUE)
440
+			&& apply_filters('FHEE__EED_Event_Single__wp_enqueue_scripts__enable_css', TRUE)
441
+		) {
442
+			// first check uploads folder
443
+			if (is_readable(get_stylesheet_directory() . $this->theme . DS . 'style.css')) {
444
+				wp_register_style(
445
+					$this->theme,
446
+					get_stylesheet_directory_uri() . $this->theme . DS . 'style.css',
447
+					array('dashicons', 'espresso_default')
448
+				);
449
+			} else {
450
+				wp_register_style(
451
+					$this->theme,
452
+					EE_TEMPLATES_URL . $this->theme . DS . 'style.css',
453
+					array('dashicons', 'espresso_default')
454
+				);
455
+			}
456
+			wp_enqueue_script($this->theme);
457
+			if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
458
+				add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
459
+			}
460
+		}
461
+	}
462
+
463
+
464
+	/**
465
+	 * display_venue
466
+	 *
467
+	 * @return    bool
468
+	 */
469
+	public static function display_venue()
470
+	{
471
+		/** @type EE_Event_Single_Config $config */
472
+		$config = EED_Event_Single::instance()->config();
473
+		$display_venue = $config->display_venue === null ? true : $config->display_venue;
474
+		$venue_name = EEH_Venue_View::venue_name();
475
+		return $display_venue && !empty($venue_name);
476
+	}
477 477
 
478 478
 
479 479
 }
@@ -487,7 +487,7 @@  discard block
 block discarded – undo
487 487
  */
488 488
 function espresso_display_venue_in_event_details()
489 489
 {
490
-    return EED_Event_Single::display_venue();
490
+	return EED_Event_Single::display_venue();
491 491
 }
492 492
 
493 493
 
Please login to merge, or discard this patch.
modules/events_archive/EED_Events_Archive.module.php 2 patches
Indentation   +190 added lines, -190 removed lines patch added patch discarded remove patch
@@ -14,13 +14,13 @@  discard block
 block discarded – undo
14 14
  */
15 15
 class EED_Events_Archive  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;
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 21
 
22 22
 
23
-    public static $espresso_event_list_ID = 0;
23
+	public static $espresso_event_list_ID = 0;
24 24
 	public static $espresso_grid_event_lists = array();
25 25
 
26 26
 	/**
@@ -28,19 +28,19 @@  discard block
 block discarded – undo
28 28
 	 */
29 29
 	protected static $using_get_the_excerpt = false;
30 30
 
31
-    /**
32
-     * Used to flag when the event list is being called from an external iframe.
33
-     *
34
-     * @var bool $iframe
35
-     */
36
-    protected static $iframe = false;
31
+	/**
32
+	 * Used to flag when the event list is being called from an external iframe.
33
+	 *
34
+	 * @var bool $iframe
35
+	 */
36
+	protected static $iframe = false;
37 37
 
38
-    /**
38
+	/**
39 39
 	 * @var \EventEspresso\core\libraries\iframe_display\EventListIframeEmbedButton $_iframe_embed_button
40 40
 	 */
41 41
 	private static $_iframe_embed_button;
42 42
 
43
-    /**
43
+	/**
44 44
 	 * @type EE_Template_Part_Manager $template_parts
45 45
 	 */
46 46
 	protected $template_parts;
@@ -63,24 +63,24 @@  discard block
 block discarded – undo
63 63
 	 *  @return 	void
64 64
 	 */
65 65
 	public static function set_hooks() {
66
-        $custom_post_types = EE_Register_CPTs::get_CPTs();
67
-        EE_Config::register_route(
68
-            $custom_post_types['espresso_events']['plural_slug'],
69
-            'Events_Archive',
70
-            'run'
71
-        );
72
-        EE_Config::register_route(
73
-            'event_list',
74
-            'Events_Archive',
75
-            'event_list'
76
-        );
77
-        EE_Config::register_route(
78
-            'iframe',
79
-            'Events_Archive',
80
-            'event_list_iframe',
81
-            'event_list'
82
-        );
83
-        add_action( 'wp_loaded', array( 'EED_Events_Archive', 'set_definitions' ), 2 );
66
+		$custom_post_types = EE_Register_CPTs::get_CPTs();
67
+		EE_Config::register_route(
68
+			$custom_post_types['espresso_events']['plural_slug'],
69
+			'Events_Archive',
70
+			'run'
71
+		);
72
+		EE_Config::register_route(
73
+			'event_list',
74
+			'Events_Archive',
75
+			'event_list'
76
+		);
77
+		EE_Config::register_route(
78
+			'iframe',
79
+			'Events_Archive',
80
+			'event_list_iframe',
81
+			'event_list'
82
+		);
83
+		add_action( 'wp_loaded', array( 'EED_Events_Archive', 'set_definitions' ), 2 );
84 84
 	}
85 85
 
86 86
 	/**
@@ -224,9 +224,9 @@  discard block
 block discarded – undo
224 224
 
225 225
 
226 226
 	/**
227
-     * most likely called by the ESPRESSO_EVENTS shortcode which uses this module to do some of it's lifting
228
-     *
229
-     * @return    void
227
+	 * most likely called by the ESPRESSO_EVENTS shortcode which uses this module to do some of it's lifting
228
+	 *
229
+	 * @return    void
230 230
 	 */
231 231
 	public function event_list() {
232 232
 		// ensure valid EE_Events_Archive_Config() object exists
@@ -237,36 +237,36 @@  discard block
 block discarded – undo
237 237
 
238 238
 
239 239
 
240
-    /**
241
-     * @access    public
242
-     * @return    void
243
-     * @throws \EE_Error
244
-     * @throws \DomainException
245
-     */
240
+	/**
241
+	 * @access    public
242
+	 * @return    void
243
+	 * @throws \EE_Error
244
+	 * @throws \DomainException
245
+	 */
246 246
 	public function event_list_iframe() {
247
-        \EED_Events_Archive::$iframe = true;
247
+		\EED_Events_Archive::$iframe = true;
248 248
 		$event_list_iframe = new EventsArchiveIframe( $this );
249 249
 		$event_list_iframe->display();
250 250
 	}
251 251
 
252 252
 
253 253
 
254
-    /**
255
-     * @access public
256
-     * @return string
257
-     */
254
+	/**
255
+	 * @access public
256
+	 * @return string
257
+	 */
258 258
 	public static function is_iframe() {
259
-        return \EED_Events_Archive::$iframe;
259
+		return \EED_Events_Archive::$iframe;
260 260
 	}
261 261
 
262 262
 
263 263
 
264
-    /**
265
-     * @access public
266
-     * @return string
267
-     */
264
+	/**
265
+	 * @access public
266
+	 * @return string
267
+	 */
268 268
 	public static function link_target() {
269
-        return \EED_Events_Archive::$iframe ? ' target="_blank"' : '';
269
+		return \EED_Events_Archive::$iframe ? ' target="_blank"' : '';
270 270
 	}
271 271
 
272 272
 
@@ -294,10 +294,10 @@  discard block
 block discarded – undo
294 294
 			}
295 295
 			// if NOT a custom template
296 296
 			if (
297
-                apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
297
+				apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
298 298
 				|| EE_Registry::instance()
299
-                    ->load_core( 'Front_Controller' )
300
-                    ->get_selected_template() !== 'archive-espresso_events.php'
299
+					->load_core( 'Front_Controller' )
300
+					->get_selected_template() !== 'archive-espresso_events.php'
301 301
 			) {
302 302
 				// don't display entry meta because the existing theme will take care of that
303 303
 				add_filter( 'FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true' );
@@ -305,16 +305,16 @@  discard block
 block discarded – undo
305 305
 				EEH_Template::load_espresso_theme_functions();
306 306
 				// because we don't know if the theme is using the_excerpt()
307 307
 				add_filter(
308
-				    'the_excerpt',
309
-                    array( 'EED_Events_Archive', 'event_details' ),
310
-                    EED_Events_Archive::EVENT_DETAILS_PRIORITY
311
-                );
308
+					'the_excerpt',
309
+					array( 'EED_Events_Archive', 'event_details' ),
310
+					EED_Events_Archive::EVENT_DETAILS_PRIORITY
311
+				);
312 312
 				// or the_content
313 313
 				add_filter(
314
-				    'the_content',
315
-                    array( 'EED_Events_Archive', 'event_details' ),
316
-                    EED_Events_Archive::EVENT_DETAILS_PRIORITY
317
-                );
314
+					'the_content',
315
+					array( 'EED_Events_Archive', 'event_details' ),
316
+					EED_Events_Archive::EVENT_DETAILS_PRIORITY
317
+				);
318 318
 				// and just in case they are running get_the_excerpt() which DESTROYS things
319 319
 				add_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1, 1 );
320 320
 				// don't display entry meta because the existing theme will take care of that
@@ -339,15 +339,15 @@  discard block
 block discarded – undo
339 339
 		}
340 340
 		if ( apply_filters( 'FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false ) ) {
341 341
 			remove_filter(
342
-			    'the_excerpt',
343
-                array( 'EED_Events_Archive', 'event_details' ),
344
-                EED_Events_Archive::EVENT_DETAILS_PRIORITY
345
-            );
342
+				'the_excerpt',
343
+				array( 'EED_Events_Archive', 'event_details' ),
344
+				EED_Events_Archive::EVENT_DETAILS_PRIORITY
345
+			);
346 346
 			remove_filter(
347
-			    'the_content',
348
-                array( 'EED_Events_Archive', 'event_details' ),
349
-                EED_Events_Archive::EVENT_DETAILS_PRIORITY
350
-            );
347
+				'the_content',
348
+				array( 'EED_Events_Archive', 'event_details' ),
349
+				EED_Events_Archive::EVENT_DETAILS_PRIORITY
350
+			);
351 351
 			$excerpt = EED_Events_Archive::event_details( $excerpt );
352 352
 		} else {
353 353
 			EED_Events_Archive::$using_get_the_excerpt = true;
@@ -438,17 +438,17 @@  discard block
 block discarded – undo
438 438
 		// no further password checks required atm
439 439
 		add_filter( 'FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true' );
440 440
 		// we need to first remove this callback from being applied to the_content() or the_excerpt()
441
-        // (otherwise it will recurse and blow up the interweb)
441
+		// (otherwise it will recurse and blow up the interweb)
442 442
 		remove_filter(
443
-		    'the_excerpt',
444
-            array( 'EED_Events_Archive', 'event_details' ),
445
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
446
-        );
443
+			'the_excerpt',
444
+			array( 'EED_Events_Archive', 'event_details' ),
445
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
446
+		);
447 447
 		remove_filter(
448
-		    'the_content',
449
-            array( 'EED_Events_Archive', 'event_details' ),
450
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
451
-        );
448
+			'the_content',
449
+			array( 'EED_Events_Archive', 'event_details' ),
450
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
451
+		);
452 452
 		remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
453 453
 		// now add additional content depending on whether event is using the_excerpt() or the_content()
454 454
 		EED_Events_Archive::instance()->template_parts = EED_Events_Archive::instance()->initialize_template_parts();
@@ -456,20 +456,20 @@  discard block
 block discarded – undo
456 456
 		$content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters( $content );
457 457
 		// re-add our main filters (or else the next event won't have them)
458 458
 		add_filter(
459
-		    'the_excerpt',
460
-            array( 'EED_Events_Archive', 'event_details' ),
461
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
462
-        );
459
+			'the_excerpt',
460
+			array( 'EED_Events_Archive', 'event_details' ),
461
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
462
+		);
463 463
 		add_filter(
464
-		    'the_content',
465
-            array( 'EED_Events_Archive', 'event_details' ),
466
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
467
-        );
464
+			'the_content',
465
+			array( 'EED_Events_Archive', 'event_details' ),
466
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
467
+		);
468 468
 		add_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1, 1 );
469 469
 		remove_filter(
470
-		    'FHEE__EED_Events_Archive__event_details__no_post_password_required',
471
-            '__return_true'
472
-        );
470
+			'FHEE__EED_Events_Archive__event_details__no_post_password_required',
471
+			'__return_true'
472
+		);
473 473
 		return $content;
474 474
 	}
475 475
 
@@ -485,15 +485,15 @@  discard block
 block discarded – undo
485 485
 		// we need to first remove this callback from being applied to the_content()
486 486
 		// (otherwise it will recurse and blow up the interweb)
487 487
 		remove_filter(
488
-		    'the_excerpt',
489
-            array( 'EED_Events_Archive', 'event_details' ),
490
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
491
-        );
488
+			'the_excerpt',
489
+			array( 'EED_Events_Archive', 'event_details' ),
490
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
491
+		);
492 492
 		remove_filter(
493
-		    'the_content',
494
-            array( 'EED_Events_Archive', 'event_details' ),
495
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
496
-        );
493
+			'the_content',
494
+			array( 'EED_Events_Archive', 'event_details' ),
495
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
496
+		);
497 497
 		remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
498 498
 		//now add additional content depending on whether event is using the_excerpt() or the_content()
499 499
 		EED_Events_Archive::_add_additional_excerpt_filters();
@@ -503,15 +503,15 @@  discard block
 block discarded – undo
503 503
 		$content = EEH_Template::locate_template( 'content-espresso_events-details.php' );
504 504
 		// re-add our main filters (or else the next event won't have them)
505 505
 		add_filter(
506
-		    'the_excerpt',
507
-            array( 'EED_Events_Archive', 'event_details' ),
508
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
509
-        );
506
+			'the_excerpt',
507
+			array( 'EED_Events_Archive', 'event_details' ),
508
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
509
+		);
510 510
 		add_filter(
511
-		    'the_content',
512
-            array( 'EED_Events_Archive', 'event_details' ),
513
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
514
-        );
511
+			'the_content',
512
+			array( 'EED_Events_Archive', 'event_details' ),
513
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
514
+		);
515 515
 		add_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1, 1 );
516 516
 		// but remove the other filters so that they don't get applied to the next post
517 517
 		EED_Events_Archive::_remove_additional_events_archive_filters();
@@ -588,20 +588,20 @@  discard block
 block discarded – undo
588 588
 	 */
589 589
 	private static function _add_additional_excerpt_filters() {
590 590
 		add_filter(
591
-		    'the_excerpt',
592
-            array( 'EED_Events_Archive', 'event_datetimes' ),
593
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
594
-        );
591
+			'the_excerpt',
592
+			array( 'EED_Events_Archive', 'event_datetimes' ),
593
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
594
+		);
595 595
 		add_filter(
596
-		    'the_excerpt',
597
-            array( 'EED_Events_Archive', 'event_tickets' ),
598
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
599
-        );
596
+			'the_excerpt',
597
+			array( 'EED_Events_Archive', 'event_tickets' ),
598
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
599
+		);
600 600
 		add_filter(
601
-		    'the_excerpt',
602
-            array( 'EED_Events_Archive', 'event_venues' ),
603
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
604
-        );
601
+			'the_excerpt',
602
+			array( 'EED_Events_Archive', 'event_venues' ),
603
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
604
+		);
605 605
 	}
606 606
 
607 607
 
@@ -614,20 +614,20 @@  discard block
 block discarded – undo
614 614
 	 */
615 615
 	private static function _add_additional_content_filters() {
616 616
 		add_filter(
617
-		    'the_content',
618
-            array( 'EED_Events_Archive', 'event_datetimes' ),
619
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
620
-        );
617
+			'the_content',
618
+			array( 'EED_Events_Archive', 'event_datetimes' ),
619
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
620
+		);
621 621
 		add_filter(
622
-		    'the_content',
623
-            array( 'EED_Events_Archive', 'event_tickets' ),
624
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
625
-        );
622
+			'the_content',
623
+			array( 'EED_Events_Archive', 'event_tickets' ),
624
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
625
+		);
626 626
 		add_filter(
627
-		    'the_content',
628
-            array( 'EED_Events_Archive', 'event_venues' ),
629
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
630
-        );
627
+			'the_content',
628
+			array( 'EED_Events_Archive', 'event_venues' ),
629
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
630
+		);
631 631
 	}
632 632
 
633 633
 
@@ -640,35 +640,35 @@  discard block
 block discarded – undo
640 640
 	 */
641 641
 	private static function _remove_additional_events_archive_filters() {
642 642
 		remove_filter(
643
-		    'the_excerpt',
644
-            array( 'EED_Events_Archive', 'event_datetimes' ),
645
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
646
-        );
643
+			'the_excerpt',
644
+			array( 'EED_Events_Archive', 'event_datetimes' ),
645
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
646
+		);
647 647
 		remove_filter(
648
-		    'the_excerpt',
649
-            array( 'EED_Events_Archive', 'event_tickets' ),
650
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
651
-        );
648
+			'the_excerpt',
649
+			array( 'EED_Events_Archive', 'event_tickets' ),
650
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
651
+		);
652 652
 		remove_filter(
653
-		    'the_excerpt',
654
-            array( 'EED_Events_Archive', 'event_venues' ),
655
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
656
-        );
653
+			'the_excerpt',
654
+			array( 'EED_Events_Archive', 'event_venues' ),
655
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
656
+		);
657 657
 		remove_filter(
658
-		    'the_content',
659
-            array( 'EED_Events_Archive', 'event_datetimes' ),
660
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
661
-        );
658
+			'the_content',
659
+			array( 'EED_Events_Archive', 'event_datetimes' ),
660
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
661
+		);
662 662
 		remove_filter(
663
-		    'the_content',
664
-            array( 'EED_Events_Archive', 'event_tickets' ),
665
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
666
-        );
663
+			'the_content',
664
+			array( 'EED_Events_Archive', 'event_tickets' ),
665
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
666
+		);
667 667
 		remove_filter(
668
-		    'the_content',
669
-            array( 'EED_Events_Archive', 'event_venues' ),
670
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
671
-        );
668
+			'the_content',
669
+			array( 'EED_Events_Archive', 'event_venues' ),
670
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
671
+		);
672 672
 	}
673 673
 
674 674
 
@@ -683,50 +683,50 @@  discard block
 block discarded – undo
683 683
 		//remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
684 684
 		remove_filter( 'the_title', array( 'EED_Events_Archive', 'the_title' ), 1 );
685 685
 		remove_filter(
686
-		    'the_excerpt',
687
-            array( 'EED_Events_Archive', 'event_details' ),
688
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
689
-        );
686
+			'the_excerpt',
687
+			array( 'EED_Events_Archive', 'event_details' ),
688
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
689
+		);
690 690
 		remove_filter(
691
-		    'the_excerpt',
692
-            array( 'EED_Events_Archive', 'event_datetimes' ),
693
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
694
-        );
691
+			'the_excerpt',
692
+			array( 'EED_Events_Archive', 'event_datetimes' ),
693
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
694
+		);
695 695
 		remove_filter(
696
-		    'the_excerpt',
697
-            array( 'EED_Events_Archive', 'event_tickets' ),
698
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
699
-        );
696
+			'the_excerpt',
697
+			array( 'EED_Events_Archive', 'event_tickets' ),
698
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
699
+		);
700 700
 		remove_filter(
701
-		    'the_excerpt',
702
-            array( 'EED_Events_Archive', 'event_venues' ),
703
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
704
-        );
701
+			'the_excerpt',
702
+			array( 'EED_Events_Archive', 'event_venues' ),
703
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
704
+		);
705 705
 		remove_filter(
706
-		    'the_content',
707
-            array( 'EED_Events_Archive', 'event_details' ),
708
-            EED_Events_Archive::EVENT_DETAILS_PRIORITY
709
-        );
706
+			'the_content',
707
+			array( 'EED_Events_Archive', 'event_details' ),
708
+			EED_Events_Archive::EVENT_DETAILS_PRIORITY
709
+		);
710 710
 		remove_filter(
711
-		    'the_content',
712
-            array( 'EED_Events_Archive', 'event_datetimes' ),
713
-            EED_Events_Archive::EVENT_DATETIMES_PRIORITY
714
-        );
711
+			'the_content',
712
+			array( 'EED_Events_Archive', 'event_datetimes' ),
713
+			EED_Events_Archive::EVENT_DATETIMES_PRIORITY
714
+		);
715 715
 		remove_filter(
716
-		    'the_content',
717
-            array( 'EED_Events_Archive', 'event_tickets' ),
718
-            EED_Events_Archive::EVENT_TICKETS_PRIORITY
719
-        );
716
+			'the_content',
717
+			array( 'EED_Events_Archive', 'event_tickets' ),
718
+			EED_Events_Archive::EVENT_TICKETS_PRIORITY
719
+		);
720 720
 		remove_filter(
721
-		    'the_content',
722
-            array( 'EED_Events_Archive', 'event_venues' ),
723
-            EED_Events_Archive::EVENT_VENUES_PRIORITY
724
-        );
721
+			'the_content',
722
+			array( 'EED_Events_Archive', 'event_venues' ),
723
+			EED_Events_Archive::EVENT_VENUES_PRIORITY
724
+		);
725 725
 		// don't display entry meta because the existing theme will take care of that
726 726
 		remove_filter(
727
-		    'FHEE__content_espresso_events_details_template__display_entry_meta',
728
-            '__return_false'
729
-        );
727
+			'FHEE__content_espresso_events_details_template__display_entry_meta',
728
+			'__return_false'
729
+		);
730 730
 	}
731 731
 
732 732
 
@@ -741,7 +741,7 @@  discard block
 block discarded – undo
741 741
 	 *  @return 	void
742 742
 	 */
743 743
 	public function load_event_list_assets() {
744
-        do_action( 'AHEE__EED_Events_Archive__before_load_assets' );
744
+		do_action( 'AHEE__EED_Events_Archive__before_load_assets' );
745 745
 		add_filter( 'FHEE_load_EE_Session', '__return_true' );
746 746
 		add_filter( 'FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true' );
747 747
 		add_action('wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ), 10 );
Please login to merge, or discard this patch.
Spacing   +172 added lines, -172 removed lines patch added patch discarded remove patch
@@ -3,7 +3,7 @@  discard block
 block discarded – undo
3 3
 use EventEspresso\core\libraries\iframe_display\EventListIframeEmbedButton;
4 4
 use EventEspresso\modules\events_archive\EventsArchiveIframe;
5 5
 
6
-defined( 'EVENT_ESPRESSO_VERSION') || exit('No direct script access allowed');
6
+defined('EVENT_ESPRESSO_VERSION') || exit('No direct script access allowed');
7 7
 
8 8
 /**
9 9
  * Event List
@@ -51,7 +51,7 @@  discard block
 block discarded – undo
51 51
 	 * @return EED_Events_Archive
52 52
 	 */
53 53
 	public static function instance() {
54
-		return parent::get_instance( __CLASS__ );
54
+		return parent::get_instance(__CLASS__);
55 55
 	}
56 56
 
57 57
 
@@ -80,7 +80,7 @@  discard block
 block discarded – undo
80 80
             'event_list_iframe',
81 81
             'event_list'
82 82
         );
83
-        add_action( 'wp_loaded', array( 'EED_Events_Archive', 'set_definitions' ), 2 );
83
+        add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
84 84
 	}
85 85
 
86 86
 	/**
@@ -90,12 +90,12 @@  discard block
 block discarded – undo
90 90
 	 *  @return 	void
91 91
 	 */
92 92
 	public static function set_hooks_admin() {
93
-		add_action( 'wp_loaded', array( 'EED_Events_Archive', 'set_definitions' ), 2 );
93
+		add_action('wp_loaded', array('EED_Events_Archive', 'set_definitions'), 2);
94 94
 		// hook into the end of the \EE_Admin_Page::_load_page_dependencies()
95 95
 		// to load assets for "espresso_events" page on the "default" route (action)
96 96
 		add_action(
97 97
 			'FHEE__EE_Admin_Page___load_page_dependencies__after_load__espresso_events__default',
98
-			array( 'EED_Events_Archive', 'event_list_iframe_embed_button' ),
98
+			array('EED_Events_Archive', 'event_list_iframe_embed_button'),
99 99
 			10
100 100
 		);
101 101
 	}
@@ -110,8 +110,8 @@  discard block
 block discarded – undo
110 110
 	 *  @return 	void
111 111
 	 */
112 112
 	public static function set_definitions() {
113
-		define( 'EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url( __FILE__ ) . 'assets' . DS );
114
-		define( 'EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace( '\\', DS, plugin_dir_path( __FILE__ )) . 'templates' . DS );
113
+		define('EVENTS_ARCHIVE_ASSETS_URL', plugin_dir_url(__FILE__).'assets'.DS);
114
+		define('EVENTS_ARCHIVE_TEMPLATES_PATH', str_replace('\\', DS, plugin_dir_path(__FILE__)).'templates'.DS);
115 115
 	}
116 116
 
117 117
 
@@ -119,10 +119,10 @@  discard block
 block discarded – undo
119 119
 	/**
120 120
 	 * set up EE_Events_Archive_Config
121 121
 	 */
122
-	protected function set_config(){
123
-		$this->set_config_section( 'template_settings' );
124
-		$this->set_config_class( 'EE_Events_Archive_Config' );
125
-		$this->set_config_name( 'EED_Events_Archive' );
122
+	protected function set_config() {
123
+		$this->set_config_section('template_settings');
124
+		$this->set_config_class('EE_Events_Archive_Config');
125
+		$this->set_config_name('EED_Events_Archive');
126 126
 	}
127 127
 
128 128
 
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
 	 * @return EventListIframeEmbedButton
132 132
 	 */
133 133
 	public static function get_iframe_embed_button() {
134
-		if ( ! self::$_iframe_embed_button instanceof EventListIframeEmbedButton ) {
134
+		if ( ! self::$_iframe_embed_button instanceof EventListIframeEmbedButton) {
135 135
 			self::$_iframe_embed_button = new EventListIframeEmbedButton();
136 136
 		}
137 137
 		return self::$_iframe_embed_button;
@@ -157,35 +157,35 @@  discard block
 block discarded – undo
157 157
 	 * @param \EE_Events_Archive_Config $config
158 158
 	 * @return \EE_Template_Part_Manager
159 159
 	 */
160
-	public function initialize_template_parts( EE_Events_Archive_Config $config = null ) {
160
+	public function initialize_template_parts(EE_Events_Archive_Config $config = null) {
161 161
 		$config = $config instanceof EE_Events_Archive_Config ? $config : $this->config();
162 162
 		EEH_Autoloader::instance()->register_template_part_autoloaders();
163 163
 		$template_parts = new EE_Template_Part_Manager();
164 164
 		$template_parts->add_template_part(
165 165
 			'tickets',
166
-			__( 'Ticket Selector', 'event_espresso' ),
166
+			__('Ticket Selector', 'event_espresso'),
167 167
 			'content-espresso_events-tickets.php',
168 168
 			$config->display_order_tickets
169 169
 		);
170 170
 		$template_parts->add_template_part(
171 171
 			'datetimes',
172
-			__( 'Dates and Times', 'event_espresso' ),
172
+			__('Dates and Times', 'event_espresso'),
173 173
 			'content-espresso_events-datetimes.php',
174 174
 			$config->display_order_datetimes
175 175
 		);
176 176
 		$template_parts->add_template_part(
177 177
 			'event',
178
-			__( 'Event Description', 'event_espresso' ),
178
+			__('Event Description', 'event_espresso'),
179 179
 			'content-espresso_events-details.php',
180 180
 			$config->display_order_event
181 181
 		);
182 182
 		$template_parts->add_template_part(
183 183
 			'venue',
184
-			__( 'Venue Information', 'event_espresso' ),
184
+			__('Venue Information', 'event_espresso'),
185 185
 			'content-espresso_events-venues.php',
186 186
 			$config->display_order_venue
187 187
 		);
188
-		do_action( 'AHEE__EED_Event_Archive__initialize_template_parts', $template_parts );
188
+		do_action('AHEE__EED_Event_Archive__initialize_template_parts', $template_parts);
189 189
 		return $template_parts;
190 190
 	}
191 191
 
@@ -198,8 +198,8 @@  discard block
 block discarded – undo
198 198
 	 * @param WP $WP
199 199
 	 * @return    void
200 200
 	 */
201
-	public function run( $WP ) {
202
-		do_action( 'AHEE__EED_Events_Archive__before_run' );
201
+	public function run($WP) {
202
+		do_action('AHEE__EED_Events_Archive__before_run');
203 203
 		// ensure valid EE_Events_Archive_Config() object exists
204 204
 		$this->set_config();
205 205
 		/** @type EE_Events_Archive_Config $config */
@@ -211,14 +211,14 @@  discard block
 block discarded – undo
211 211
 		EEH_Event_Query::add_query_filters();
212 212
 		// set params that will get used by the filters
213 213
 		EEH_Event_Query::set_query_params(
214
-			'', 	// month
215
-			'', 	// category
216
-			$config->display_expired_events, 	// show_expired
217
-			'start_date', 	// orderby
214
+			'', // month
215
+			'', // category
216
+			$config->display_expired_events, // show_expired
217
+			'start_date', // orderby
218 218
 			'ASC' 	// sort
219 219
 		);
220 220
 		// check what template is loaded
221
-		add_filter( 'template_include',  array( $this, 'template_include' ), 999, 1 );
221
+		add_filter('template_include', array($this, 'template_include'), 999, 1);
222 222
 	}
223 223
 
224 224
 
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
      */
246 246
 	public function event_list_iframe() {
247 247
         \EED_Events_Archive::$iframe = true;
248
-		$event_list_iframe = new EventsArchiveIframe( $this );
248
+		$event_list_iframe = new EventsArchiveIframe($this);
249 249
 		$event_list_iframe->display();
250 250
 	}
251 251
 
@@ -283,42 +283,42 @@  discard block
 block discarded – undo
283 283
 	 * @param string $template
284 284
 	 * @return    string
285 285
 	 */
286
-	public function template_include( $template = '' ) {
286
+	public function template_include($template = '') {
287 287
 		// don't add content filter for dedicated EE child themes or private posts
288
-		if ( ! EEH_Template::is_espresso_theme() ) {
288
+		if ( ! EEH_Template::is_espresso_theme()) {
289 289
 			/** @type EE_Events_Archive_Config $config */
290 290
 			$config = $this->config();
291 291
 			// add status banner ?
292
-			if ( $config->display_status_banner ) {
293
-				add_filter( 'the_title', array( 'EED_Events_Archive', 'the_title' ), 100, 2 );
292
+			if ($config->display_status_banner) {
293
+				add_filter('the_title', array('EED_Events_Archive', 'the_title'), 100, 2);
294 294
 			}
295 295
 			// if NOT a custom template
296 296
 			if (
297 297
                 apply_filters('FHEE__EED_Event_Archive__template_include__allow_custom_selected_template', false)
298 298
 				|| EE_Registry::instance()
299
-                    ->load_core( 'Front_Controller' )
299
+                    ->load_core('Front_Controller')
300 300
                     ->get_selected_template() !== 'archive-espresso_events.php'
301 301
 			) {
302 302
 				// don't display entry meta because the existing theme will take care of that
303
-				add_filter( 'FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true' );
303
+				add_filter('FHEE__EED_Events_Archive__template_include__events_list_active', '__return_true');
304 304
 			// load functions.php file for the theme (loaded by WP if using child theme)
305 305
 				EEH_Template::load_espresso_theme_functions();
306 306
 				// because we don't know if the theme is using the_excerpt()
307 307
 				add_filter(
308 308
 				    'the_excerpt',
309
-                    array( 'EED_Events_Archive', 'event_details' ),
309
+                    array('EED_Events_Archive', 'event_details'),
310 310
                     EED_Events_Archive::EVENT_DETAILS_PRIORITY
311 311
                 );
312 312
 				// or the_content
313 313
 				add_filter(
314 314
 				    'the_content',
315
-                    array( 'EED_Events_Archive', 'event_details' ),
315
+                    array('EED_Events_Archive', 'event_details'),
316 316
                     EED_Events_Archive::EVENT_DETAILS_PRIORITY
317 317
                 );
318 318
 				// and just in case they are running get_the_excerpt() which DESTROYS things
319
-				add_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1, 1 );
319
+				add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
320 320
 				// don't display entry meta because the existing theme will take care of that
321
-				add_filter( 'FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false' );
321
+				add_filter('FHEE__content_espresso_events_details_template__display_entry_meta', '__return_false');
322 322
 			}
323 323
 		}
324 324
 		return $template;
@@ -333,25 +333,25 @@  discard block
 block discarded – undo
333 333
 	 * 	@param		string 	$excerpt
334 334
 	 * 	@return 		string
335 335
 	 */
336
-	public static function get_the_excerpt( $excerpt = '' ) {
337
-		if ( post_password_required() ) {
336
+	public static function get_the_excerpt($excerpt = '') {
337
+		if (post_password_required()) {
338 338
 			return $excerpt;
339 339
 		}
340
-		if ( apply_filters( 'FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false ) ) {
340
+		if (apply_filters('FHEE__EED_Events_Archive__get_the_excerpt__theme_uses_get_the_excerpt', false)) {
341 341
 			remove_filter(
342 342
 			    'the_excerpt',
343
-                array( 'EED_Events_Archive', 'event_details' ),
343
+                array('EED_Events_Archive', 'event_details'),
344 344
                 EED_Events_Archive::EVENT_DETAILS_PRIORITY
345 345
             );
346 346
 			remove_filter(
347 347
 			    'the_content',
348
-                array( 'EED_Events_Archive', 'event_details' ),
348
+                array('EED_Events_Archive', 'event_details'),
349 349
                 EED_Events_Archive::EVENT_DETAILS_PRIORITY
350 350
             );
351
-			$excerpt = EED_Events_Archive::event_details( $excerpt );
351
+			$excerpt = EED_Events_Archive::event_details($excerpt);
352 352
 		} else {
353 353
 			EED_Events_Archive::$using_get_the_excerpt = true;
354
-			add_filter( 'wp_trim_excerpt', array( 'EED_Events_Archive', 'end_get_the_excerpt' ), 999, 1 );
354
+			add_filter('wp_trim_excerpt', array('EED_Events_Archive', 'end_get_the_excerpt'), 999, 1);
355 355
 		}
356 356
 		return $excerpt;
357 357
 	}
@@ -365,7 +365,7 @@  discard block
 block discarded – undo
365 365
 	 * @param  string $text
366 366
 	 * @return string
367 367
 	 */
368
-	public static function end_get_the_excerpt( $text = '' ) {
368
+	public static function end_get_the_excerpt($text = '') {
369 369
 		EED_Events_Archive::$using_get_the_excerpt = false;
370 370
 		return $text;
371 371
 	}
@@ -380,10 +380,10 @@  discard block
 block discarded – undo
380 380
 	 * @param 		string 		$id
381 381
 	 * @return 		string
382 382
 	 */
383
-	public static function the_title( $title = '', $id = '' ) {
383
+	public static function the_title($title = '', $id = '') {
384 384
 	global $post;
385
-	if ( $post instanceof WP_Post ) {
386
-		return in_the_loop() && $post->ID == $id ? espresso_event_status_banner( $post->ID  ) . $title :  $title;
385
+	if ($post instanceof WP_Post) {
386
+		return in_the_loop() && $post->ID == $id ? espresso_event_status_banner($post->ID).$title : $title;
387 387
 	}
388 388
 	return $title;
389 389
 }
@@ -397,7 +397,7 @@  discard block
 block discarded – undo
397 397
 	 * 	@param		string 	$content
398 398
 	 * 	@return 		string
399 399
 	 */
400
-	public static function event_details( $content ) {
400
+	public static function event_details($content) {
401 401
 		global $post;
402 402
 		static $current_post_ID = 0;
403 403
 		if (
@@ -406,8 +406,8 @@  discard block
 block discarded – undo
406 406
 			&& ! EED_Events_Archive::$using_get_the_excerpt
407 407
 			&& ! post_password_required()
408 408
 			&& (
409
-				apply_filters( 'FHEE__EES_Espresso_Events__process_shortcode__true', false )
410
-				|| ! apply_filters( 'FHEE__content_espresso_events__template_loaded', false )
409
+				apply_filters('FHEE__EES_Espresso_Events__process_shortcode__true', false)
410
+				|| ! apply_filters('FHEE__content_espresso_events__template_loaded', false)
411 411
 			)
412 412
 		) {
413 413
 			// Set current post ID to prevent showing content twice, but only if headers have definitely been sent.
@@ -416,8 +416,8 @@  discard block
 block discarded – undo
416 416
 			// We want to allow those plugins to still do their thing and have access to our content, but depending on
417 417
 			// how your event content is being displayed (shortcode, CPT route, etc), this filter can get applied twice,
418 418
 			// so the following allows this filter to be applied multiple times, but only once for real
419
-			$current_post_ID = did_action( 'loop_start' ) ? $post->ID : 0;
420
-			if ( EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->use_sortable_display_order ) {
419
+			$current_post_ID = did_action('loop_start') ? $post->ID : 0;
420
+			if (EE_Registry::instance()->CFG->template_settings->EED_Events_Archive->use_sortable_display_order) {
421 421
 				$content = \EED_Events_Archive::use_sortable_display_order();
422 422
 			} else {
423 423
 				$content = \EED_Events_Archive::use_filterable_display_order();
@@ -436,36 +436,36 @@  discard block
 block discarded – undo
436 436
 	 */
437 437
 	protected static function use_sortable_display_order() {
438 438
 		// no further password checks required atm
439
-		add_filter( 'FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true' );
439
+		add_filter('FHEE__EED_Events_Archive__event_details__no_post_password_required', '__return_true');
440 440
 		// we need to first remove this callback from being applied to the_content() or the_excerpt()
441 441
         // (otherwise it will recurse and blow up the interweb)
442 442
 		remove_filter(
443 443
 		    'the_excerpt',
444
-            array( 'EED_Events_Archive', 'event_details' ),
444
+            array('EED_Events_Archive', 'event_details'),
445 445
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
446 446
         );
447 447
 		remove_filter(
448 448
 		    'the_content',
449
-            array( 'EED_Events_Archive', 'event_details' ),
449
+            array('EED_Events_Archive', 'event_details'),
450 450
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
451 451
         );
452
-		remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
452
+		remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
453 453
 		// now add additional content depending on whether event is using the_excerpt() or the_content()
454 454
 		EED_Events_Archive::instance()->template_parts = EED_Events_Archive::instance()->initialize_template_parts();
455
-		$content = EEH_Template::locate_template( 'content-espresso_events-details.php' );
456
-		$content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters( $content );
455
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
456
+		$content = EED_Events_Archive::instance()->template_parts->apply_template_part_filters($content);
457 457
 		// re-add our main filters (or else the next event won't have them)
458 458
 		add_filter(
459 459
 		    'the_excerpt',
460
-            array( 'EED_Events_Archive', 'event_details' ),
460
+            array('EED_Events_Archive', 'event_details'),
461 461
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
462 462
         );
463 463
 		add_filter(
464 464
 		    'the_content',
465
-            array( 'EED_Events_Archive', 'event_details' ),
465
+            array('EED_Events_Archive', 'event_details'),
466 466
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
467 467
         );
468
-		add_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1, 1 );
468
+		add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
469 469
 		remove_filter(
470 470
 		    'FHEE__EED_Events_Archive__event_details__no_post_password_required',
471 471
             '__return_true'
@@ -486,36 +486,36 @@  discard block
 block discarded – undo
486 486
 		// (otherwise it will recurse and blow up the interweb)
487 487
 		remove_filter(
488 488
 		    'the_excerpt',
489
-            array( 'EED_Events_Archive', 'event_details' ),
489
+            array('EED_Events_Archive', 'event_details'),
490 490
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
491 491
         );
492 492
 		remove_filter(
493 493
 		    'the_content',
494
-            array( 'EED_Events_Archive', 'event_details' ),
494
+            array('EED_Events_Archive', 'event_details'),
495 495
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
496 496
         );
497
-		remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
497
+		remove_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1);
498 498
 		//now add additional content depending on whether event is using the_excerpt() or the_content()
499 499
 		EED_Events_Archive::_add_additional_excerpt_filters();
500 500
 		EED_Events_Archive::_add_additional_content_filters();
501
-		do_action( 'AHEE__EED_Events_Archive__use_filterable_display_order__after_add_filters' );
501
+		do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_add_filters');
502 502
 		// now load our template
503
-		$content = EEH_Template::locate_template( 'content-espresso_events-details.php' );
503
+		$content = EEH_Template::locate_template('content-espresso_events-details.php');
504 504
 		// re-add our main filters (or else the next event won't have them)
505 505
 		add_filter(
506 506
 		    'the_excerpt',
507
-            array( 'EED_Events_Archive', 'event_details' ),
507
+            array('EED_Events_Archive', 'event_details'),
508 508
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
509 509
         );
510 510
 		add_filter(
511 511
 		    'the_content',
512
-            array( 'EED_Events_Archive', 'event_details' ),
512
+            array('EED_Events_Archive', 'event_details'),
513 513
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
514 514
         );
515
-		add_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1, 1 );
515
+		add_filter('get_the_excerpt', array('EED_Events_Archive', 'get_the_excerpt'), 1, 1);
516 516
 		// but remove the other filters so that they don't get applied to the next post
517 517
 		EED_Events_Archive::_remove_additional_events_archive_filters();
518
-		do_action( 'AHEE__EED_Events_Archive__use_filterable_display_order__after_remove_filters' );
518
+		do_action('AHEE__EED_Events_Archive__use_filterable_display_order__after_remove_filters');
519 519
 		// we're not returning the $content directly because the template we are loading uses the_content (or the_excerpt)
520 520
 		//return ! empty( $template ) ? $template : $content;
521 521
 		return $content;
@@ -530,11 +530,11 @@  discard block
 block discarded – undo
530 530
 	 * 	@param		string 	$content
531 531
 	 *  	@return 		string
532 532
 	 */
533
-	public static function event_datetimes( $content ) {
534
-		if ( post_password_required() ) {
533
+	public static function event_datetimes($content) {
534
+		if (post_password_required()) {
535 535
 			return $content;
536 536
 		}
537
-		return EEH_Template::locate_template( 'content-espresso_events-datetimes.php' ) . $content;
537
+		return EEH_Template::locate_template('content-espresso_events-datetimes.php').$content;
538 538
 	}
539 539
 
540 540
 	/**
@@ -544,11 +544,11 @@  discard block
 block discarded – undo
544 544
 	 * 	@param		string 	$content
545 545
 	 *  	@return 		string
546 546
 	 */
547
-	public static function event_tickets( $content ) {
548
-		if ( post_password_required() ) {
547
+	public static function event_tickets($content) {
548
+		if (post_password_required()) {
549 549
 			return $content;
550 550
 		}
551
-		return EEH_Template::locate_template( 'content-espresso_events-tickets.php' ) . $content;
551
+		return EEH_Template::locate_template('content-espresso_events-tickets.php').$content;
552 552
 	}
553 553
 
554 554
 
@@ -560,8 +560,8 @@  discard block
 block discarded – undo
560 560
 	 * @param    string $content
561 561
 	 * @return    string
562 562
 	 */
563
-	public static function event_venue( $content ) {
564
-		return EED_Events_Archive::event_venues( $content );
563
+	public static function event_venue($content) {
564
+		return EED_Events_Archive::event_venues($content);
565 565
 	}
566 566
 
567 567
 	/**
@@ -571,11 +571,11 @@  discard block
 block discarded – undo
571 571
 	 * 	@param		string 	$content
572 572
 	 *  	@return 		string
573 573
 	 */
574
-	public static function event_venues( $content ) {
575
-		if ( post_password_required() ) {
574
+	public static function event_venues($content) {
575
+		if (post_password_required()) {
576 576
 			return $content;
577 577
 		}
578
-		return $content . EEH_Template::locate_template( 'content-espresso_events-venues.php' );
578
+		return $content.EEH_Template::locate_template('content-espresso_events-venues.php');
579 579
 	}
580 580
 
581 581
 
@@ -589,17 +589,17 @@  discard block
 block discarded – undo
589 589
 	private static function _add_additional_excerpt_filters() {
590 590
 		add_filter(
591 591
 		    'the_excerpt',
592
-            array( 'EED_Events_Archive', 'event_datetimes' ),
592
+            array('EED_Events_Archive', 'event_datetimes'),
593 593
             EED_Events_Archive::EVENT_DATETIMES_PRIORITY
594 594
         );
595 595
 		add_filter(
596 596
 		    'the_excerpt',
597
-            array( 'EED_Events_Archive', 'event_tickets' ),
597
+            array('EED_Events_Archive', 'event_tickets'),
598 598
             EED_Events_Archive::EVENT_TICKETS_PRIORITY
599 599
         );
600 600
 		add_filter(
601 601
 		    'the_excerpt',
602
-            array( 'EED_Events_Archive', 'event_venues' ),
602
+            array('EED_Events_Archive', 'event_venues'),
603 603
             EED_Events_Archive::EVENT_VENUES_PRIORITY
604 604
         );
605 605
 	}
@@ -615,17 +615,17 @@  discard block
 block discarded – undo
615 615
 	private static function _add_additional_content_filters() {
616 616
 		add_filter(
617 617
 		    'the_content',
618
-            array( 'EED_Events_Archive', 'event_datetimes' ),
618
+            array('EED_Events_Archive', 'event_datetimes'),
619 619
             EED_Events_Archive::EVENT_DATETIMES_PRIORITY
620 620
         );
621 621
 		add_filter(
622 622
 		    'the_content',
623
-            array( 'EED_Events_Archive', 'event_tickets' ),
623
+            array('EED_Events_Archive', 'event_tickets'),
624 624
             EED_Events_Archive::EVENT_TICKETS_PRIORITY
625 625
         );
626 626
 		add_filter(
627 627
 		    'the_content',
628
-            array( 'EED_Events_Archive', 'event_venues' ),
628
+            array('EED_Events_Archive', 'event_venues'),
629 629
             EED_Events_Archive::EVENT_VENUES_PRIORITY
630 630
         );
631 631
 	}
@@ -641,32 +641,32 @@  discard block
 block discarded – undo
641 641
 	private static function _remove_additional_events_archive_filters() {
642 642
 		remove_filter(
643 643
 		    'the_excerpt',
644
-            array( 'EED_Events_Archive', 'event_datetimes' ),
644
+            array('EED_Events_Archive', 'event_datetimes'),
645 645
             EED_Events_Archive::EVENT_DATETIMES_PRIORITY
646 646
         );
647 647
 		remove_filter(
648 648
 		    'the_excerpt',
649
-            array( 'EED_Events_Archive', 'event_tickets' ),
649
+            array('EED_Events_Archive', 'event_tickets'),
650 650
             EED_Events_Archive::EVENT_TICKETS_PRIORITY
651 651
         );
652 652
 		remove_filter(
653 653
 		    'the_excerpt',
654
-            array( 'EED_Events_Archive', 'event_venues' ),
654
+            array('EED_Events_Archive', 'event_venues'),
655 655
             EED_Events_Archive::EVENT_VENUES_PRIORITY
656 656
         );
657 657
 		remove_filter(
658 658
 		    'the_content',
659
-            array( 'EED_Events_Archive', 'event_datetimes' ),
659
+            array('EED_Events_Archive', 'event_datetimes'),
660 660
             EED_Events_Archive::EVENT_DATETIMES_PRIORITY
661 661
         );
662 662
 		remove_filter(
663 663
 		    'the_content',
664
-            array( 'EED_Events_Archive', 'event_tickets' ),
664
+            array('EED_Events_Archive', 'event_tickets'),
665 665
             EED_Events_Archive::EVENT_TICKETS_PRIORITY
666 666
         );
667 667
 		remove_filter(
668 668
 		    'the_content',
669
-            array( 'EED_Events_Archive', 'event_venues' ),
669
+            array('EED_Events_Archive', 'event_venues'),
670 670
             EED_Events_Archive::EVENT_VENUES_PRIORITY
671 671
         );
672 672
 	}
@@ -681,45 +681,45 @@  discard block
 block discarded – undo
681 681
 	 */
682 682
 	public static function remove_all_events_archive_filters() {
683 683
 		//remove_filter( 'get_the_excerpt', array( 'EED_Events_Archive', 'get_the_excerpt' ), 1 );
684
-		remove_filter( 'the_title', array( 'EED_Events_Archive', 'the_title' ), 1 );
684
+		remove_filter('the_title', array('EED_Events_Archive', 'the_title'), 1);
685 685
 		remove_filter(
686 686
 		    'the_excerpt',
687
-            array( 'EED_Events_Archive', 'event_details' ),
687
+            array('EED_Events_Archive', 'event_details'),
688 688
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
689 689
         );
690 690
 		remove_filter(
691 691
 		    'the_excerpt',
692
-            array( 'EED_Events_Archive', 'event_datetimes' ),
692
+            array('EED_Events_Archive', 'event_datetimes'),
693 693
             EED_Events_Archive::EVENT_DATETIMES_PRIORITY
694 694
         );
695 695
 		remove_filter(
696 696
 		    'the_excerpt',
697
-            array( 'EED_Events_Archive', 'event_tickets' ),
697
+            array('EED_Events_Archive', 'event_tickets'),
698 698
             EED_Events_Archive::EVENT_TICKETS_PRIORITY
699 699
         );
700 700
 		remove_filter(
701 701
 		    'the_excerpt',
702
-            array( 'EED_Events_Archive', 'event_venues' ),
702
+            array('EED_Events_Archive', 'event_venues'),
703 703
             EED_Events_Archive::EVENT_VENUES_PRIORITY
704 704
         );
705 705
 		remove_filter(
706 706
 		    'the_content',
707
-            array( 'EED_Events_Archive', 'event_details' ),
707
+            array('EED_Events_Archive', 'event_details'),
708 708
             EED_Events_Archive::EVENT_DETAILS_PRIORITY
709 709
         );
710 710
 		remove_filter(
711 711
 		    'the_content',
712
-            array( 'EED_Events_Archive', 'event_datetimes' ),
712
+            array('EED_Events_Archive', 'event_datetimes'),
713 713
             EED_Events_Archive::EVENT_DATETIMES_PRIORITY
714 714
         );
715 715
 		remove_filter(
716 716
 		    'the_content',
717
-            array( 'EED_Events_Archive', 'event_tickets' ),
717
+            array('EED_Events_Archive', 'event_tickets'),
718 718
             EED_Events_Archive::EVENT_TICKETS_PRIORITY
719 719
         );
720 720
 		remove_filter(
721 721
 		    'the_content',
722
-            array( 'EED_Events_Archive', 'event_venues' ),
722
+            array('EED_Events_Archive', 'event_venues'),
723 723
             EED_Events_Archive::EVENT_VENUES_PRIORITY
724 724
         );
725 725
 		// don't display entry meta because the existing theme will take care of that
@@ -741,12 +741,12 @@  discard block
 block discarded – undo
741 741
 	 *  @return 	void
742 742
 	 */
743 743
 	public function load_event_list_assets() {
744
-        do_action( 'AHEE__EED_Events_Archive__before_load_assets' );
745
-		add_filter( 'FHEE_load_EE_Session', '__return_true' );
746
-		add_filter( 'FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true' );
747
-		add_action('wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ), 10 );
748
-		if ( EE_Registry::instance()->CFG->map_settings->use_google_maps ) {
749
-			add_action('wp_enqueue_scripts', array( 'EEH_Maps', 'espresso_google_map_js' ), 11 );
744
+        do_action('AHEE__EED_Events_Archive__before_load_assets');
745
+		add_filter('FHEE_load_EE_Session', '__return_true');
746
+		add_filter('FHEE__EED_Ticket_Selector__load_tckt_slctr_assets', '__return_true');
747
+		add_action('wp_enqueue_scripts', array($this, 'wp_enqueue_scripts'), 10);
748
+		if (EE_Registry::instance()->CFG->map_settings->use_google_maps) {
749
+			add_action('wp_enqueue_scripts', array('EEH_Maps', 'espresso_google_map_js'), 11);
750 750
 		}
751 751
 	}
752 752
 
@@ -763,13 +763,13 @@  discard block
 block discarded – undo
763 763
 	 */
764 764
 	public function wp_enqueue_scripts() {
765 765
 		// get some style
766
-		if ( apply_filters( 'FHEE_enable_default_espresso_css', FALSE ) ) {
766
+		if (apply_filters('FHEE_enable_default_espresso_css', FALSE)) {
767 767
 			// first check uploads folder
768
-			if ( EEH_File::is_readable( get_stylesheet_directory() . $this->theme . DS . 'style.css' )) {
769
-				wp_register_style( $this->theme, get_stylesheet_directory_uri() . $this->theme . DS . 'style.css', array( 'dashicons', 'espresso_default' ));
768
+			if (EEH_File::is_readable(get_stylesheet_directory().$this->theme.DS.'style.css')) {
769
+				wp_register_style($this->theme, get_stylesheet_directory_uri().$this->theme.DS.'style.css', array('dashicons', 'espresso_default'));
770 770
 			} else {
771 771
 		}
772
-		wp_enqueue_style( $this->theme );
772
+		wp_enqueue_style($this->theme);
773 773
 
774 774
 	}
775 775
 }
@@ -787,8 +787,8 @@  discard block
 block discarded – undo
787 787
 	 */
788 788
 	public static function template_settings_form() {
789 789
 	$template_settings = EE_Registry::instance()->CFG->template_settings;
790
-	$template_settings->EED_Events_Archive = isset( $template_settings->EED_Events_Archive ) ? $template_settings->EED_Events_Archive : new EE_Events_Archive_Config();
791
-	$template_settings->EED_Events_Archive = apply_filters( 'FHEE__EED_Events_Archive__template_settings_form__event_list_config', $template_settings->EED_Events_Archive );
790
+	$template_settings->EED_Events_Archive = isset($template_settings->EED_Events_Archive) ? $template_settings->EED_Events_Archive : new EE_Events_Archive_Config();
791
+	$template_settings->EED_Events_Archive = apply_filters('FHEE__EED_Events_Archive__template_settings_form__event_list_config', $template_settings->EED_Events_Archive);
792 792
 	$events_archive_settings = array(
793 793
 		'display_status_banner' => 0,
794 794
 		'display_description' => 1,
@@ -797,8 +797,8 @@  discard block
 block discarded – undo
797 797
 		'display_venue' => 0,
798 798
 		'display_expired_events' => 0
799 799
 	);
800
-	$events_archive_settings = array_merge( $events_archive_settings, (array)$template_settings->EED_Events_Archive );
801
-	EEH_Template::display_template( EVENTS_ARCHIVE_TEMPLATES_PATH . 'admin-event-list-settings.template.php', $events_archive_settings );
800
+	$events_archive_settings = array_merge($events_archive_settings, (array) $template_settings->EED_Events_Archive);
801
+	EEH_Template::display_template(EVENTS_ARCHIVE_TEMPLATES_PATH.'admin-event-list-settings.template.php', $events_archive_settings);
802 802
 }
803 803
 
804 804
 
@@ -814,16 +814,16 @@  discard block
 block discarded – undo
814 814
 	 *  @param 	EE_Request_Handler $REQ
815 815
 	 *  @return 	EE_Template_Config
816 816
 	 */
817
-	public static function update_template_settings( $CFG, $REQ ) {
817
+	public static function update_template_settings($CFG, $REQ) {
818 818
 		$CFG->EED_Events_Archive = new EE_Events_Archive_Config();
819 819
 		// unless we are resetting the config...
820
-		if ( ! isset( $REQ['EED_Events_Archive_reset_event_list_settings'] ) || absint( $REQ['EED_Events_Archive_reset_event_list_settings'] ) !== 1 ) {
821
-			$CFG->EED_Events_Archive->display_status_banner = isset( $REQ['EED_Events_Archive_display_status_banner'] ) ? absint( $REQ['EED_Events_Archive_display_status_banner'] ) : 0;
822
-			$CFG->EED_Events_Archive->display_description = isset( $REQ['EED_Events_Archive_display_description'] ) ? absint( $REQ['EED_Events_Archive_display_description'] ) : 1;
823
-			$CFG->EED_Events_Archive->display_ticket_selector = isset( $REQ['EED_Events_Archive_display_ticket_selector'] ) ? absint( $REQ['EED_Events_Archive_display_ticket_selector'] ) : 0;
824
-			$CFG->EED_Events_Archive->display_datetimes = isset( $REQ['EED_Events_Archive_display_datetimes'] ) ? absint( $REQ['EED_Events_Archive_display_datetimes'] ) : 1;
825
-			$CFG->EED_Events_Archive->display_venue = isset( $REQ['EED_Events_Archive_display_venue'] ) ? absint( $REQ['EED_Events_Archive_display_venue'] ) : 0;
826
-			$CFG->EED_Events_Archive->display_expired_events = isset( $REQ['EED_Events_Archive_display_expired_events'] ) ? absint( $REQ['EED_Events_Archive_display_expired_events'] ) : 0;			}
820
+		if ( ! isset($REQ['EED_Events_Archive_reset_event_list_settings']) || absint($REQ['EED_Events_Archive_reset_event_list_settings']) !== 1) {
821
+			$CFG->EED_Events_Archive->display_status_banner = isset($REQ['EED_Events_Archive_display_status_banner']) ? absint($REQ['EED_Events_Archive_display_status_banner']) : 0;
822
+			$CFG->EED_Events_Archive->display_description = isset($REQ['EED_Events_Archive_display_description']) ? absint($REQ['EED_Events_Archive_display_description']) : 1;
823
+			$CFG->EED_Events_Archive->display_ticket_selector = isset($REQ['EED_Events_Archive_display_ticket_selector']) ? absint($REQ['EED_Events_Archive_display_ticket_selector']) : 0;
824
+			$CFG->EED_Events_Archive->display_datetimes = isset($REQ['EED_Events_Archive_display_datetimes']) ? absint($REQ['EED_Events_Archive_display_datetimes']) : 1;
825
+			$CFG->EED_Events_Archive->display_venue = isset($REQ['EED_Events_Archive_display_venue']) ? absint($REQ['EED_Events_Archive_display_venue']) : 0;
826
+			$CFG->EED_Events_Archive->display_expired_events = isset($REQ['EED_Events_Archive_display_expired_events']) ? absint($REQ['EED_Events_Archive_display_expired_events']) : 0; }
827 827
 		return $CFG;
828 828
 	}
829 829
 
@@ -836,10 +836,10 @@  discard block
 block discarded – undo
836 836
 	 * @param string $extra_class
837 837
 	 * @return    string
838 838
 	 */
839
-	public static function event_list_css( $extra_class = '' ) {
840
-		$event_list_css = ! empty( $extra_class ) ? array( $extra_class ) : array();
839
+	public static function event_list_css($extra_class = '') {
840
+		$event_list_css = ! empty($extra_class) ? array($extra_class) : array();
841 841
 		$event_list_css[] = 'espresso-event-list-event';
842
-		return implode( ' ', $event_list_css );
842
+		return implode(' ', $event_list_css);
843 843
 	}
844 844
 
845 845
 
@@ -866,9 +866,9 @@  discard block
 block discarded – undo
866 866
 	 * @param $value
867 867
 	 * @return    bool
868 868
 	 */
869
-	public static function display_description( $value ) {
869
+	public static function display_description($value) {
870 870
 		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
871
-		$display_description= isset( $config->display_description ) ? $config->display_description : 1;
871
+		$display_description = isset($config->display_description) ? $config->display_description : 1;
872 872
 		return $display_description === $value ? TRUE : FALSE;
873 873
 	}
874 874
 
@@ -881,7 +881,7 @@  discard block
 block discarded – undo
881 881
 	 */
882 882
 	public static function display_ticket_selector() {
883 883
 		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
884
-		return isset( $config->display_ticket_selector ) && $config->display_ticket_selector ? TRUE : FALSE;
884
+		return isset($config->display_ticket_selector) && $config->display_ticket_selector ? TRUE : FALSE;
885 885
 	}
886 886
 
887 887
 
@@ -894,7 +894,7 @@  discard block
 block discarded – undo
894 894
 	 */
895 895
 	public static function display_venue() {
896 896
 		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
897
-		return isset( $config->display_venue ) && $config->display_venue && EEH_Venue_View::venue_name() ? TRUE : FALSE;
897
+		return isset($config->display_venue) && $config->display_venue && EEH_Venue_View::venue_name() ? TRUE : FALSE;
898 898
 	}
899 899
 
900 900
 
@@ -906,7 +906,7 @@  discard block
 block discarded – undo
906 906
 	 */
907 907
 	public static function display_datetimes() {
908 908
 		$config = EE_Registry::instance()->CFG->template_settings->EED_Events_Archive;
909
-		return isset( $config->display_datetimes ) && $config->display_datetimes ? TRUE : FALSE;
909
+		return isset($config->display_datetimes) && $config->display_datetimes ? TRUE : FALSE;
910 910
 }
911 911
 
912 912
 
@@ -921,7 +921,7 @@  discard block
 block discarded – undo
921 921
 	 *  @return 	string
922 922
 	 */
923 923
 	public static function event_list_title() {
924
-		return apply_filters( 'FHEE__archive_espresso_events_template__upcoming_events_h1', __( 'Upcoming Events', 'event_espresso' ));
924
+		return apply_filters('FHEE__archive_espresso_events_template__upcoming_events_h1', __('Upcoming Events', 'event_espresso'));
925 925
 	}
926 926
 
927 927
 
@@ -930,11 +930,11 @@  discard block
 block discarded – undo
930 930
 	/**
931 931
 	 * 	@since 4.4.0
932 932
 	 */
933
-	public static function _doing_it_wrong_notice( $function = '' ) {
933
+	public static function _doing_it_wrong_notice($function = '') {
934 934
 		EE_Error::doing_it_wrong(
935 935
 			__FUNCTION__,
936 936
 			sprintf(
937
-				__( 'EED_Events_Archive::%1$s was moved to EEH_Event_Query::%1$s:%2$sPlease update your existing code because the method it calls will be removed in version %3$s', 'event_espresso' ),
937
+				__('EED_Events_Archive::%1$s was moved to EEH_Event_Query::%1$s:%2$sPlease update your existing code because the method it calls will be removed in version %3$s', 'event_espresso'),
938 938
 				$function,
939 939
 				'<br />',
940 940
 				'4.6.0'
@@ -956,89 +956,89 @@  discard block
 block discarded – undo
956 956
 	 * 	@deprecated
957 957
 	 * 	@since 4.4.0
958 958
 	 */
959
-	public function posts_fields( $SQL, WP_Query $wp_query ) {
960
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
961
-		return EEH_Event_Query::posts_fields( $SQL, $wp_query );
959
+	public function posts_fields($SQL, WP_Query $wp_query) {
960
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
961
+		return EEH_Event_Query::posts_fields($SQL, $wp_query);
962 962
 	}
963 963
 	/**
964 964
 	 * 	@deprecated
965 965
 	 * 	@since 4.4.0
966 966
 	 */
967
-	public static function posts_fields_sql_for_orderby( $orderby_params = array() ) {
968
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
969
-		return EEH_Event_Query::posts_fields_sql_for_orderby( $orderby_params );
967
+	public static function posts_fields_sql_for_orderby($orderby_params = array()) {
968
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
969
+		return EEH_Event_Query::posts_fields_sql_for_orderby($orderby_params);
970 970
 	}
971 971
 	/**
972 972
 	 * 	@deprecated
973 973
 	 * 	@since 4.4.0
974 974
 	 */
975
-	public function posts_join( $SQL, WP_Query $wp_query ) {
976
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
977
-		return EEH_Event_Query::posts_join( $SQL, $wp_query );
975
+	public function posts_join($SQL, WP_Query $wp_query) {
976
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
977
+		return EEH_Event_Query::posts_join($SQL, $wp_query);
978 978
 	}
979 979
 	/**
980 980
 	 * 	@deprecated
981 981
 	 * 	@since 4.4.0
982 982
 	 */
983
-	public static function posts_join_sql_for_terms( $join_terms = NULL ) {
984
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
985
-		return EEH_Event_Query::posts_join_sql_for_terms( $join_terms );
983
+	public static function posts_join_sql_for_terms($join_terms = NULL) {
984
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
985
+		return EEH_Event_Query::posts_join_sql_for_terms($join_terms);
986 986
 	}
987 987
 	/**
988 988
 	 * 	@deprecated
989 989
 	 * 	@since 4.4.0
990 990
 	 */
991
-	public static function posts_join_for_orderby( $orderby_params = array() ) {
992
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
993
-		return EEH_Event_Query::posts_join_for_orderby( $orderby_params );
991
+	public static function posts_join_for_orderby($orderby_params = array()) {
992
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
993
+		return EEH_Event_Query::posts_join_for_orderby($orderby_params);
994 994
 	}
995 995
 	/**
996 996
 	 * 	@deprecated
997 997
 	 * 	@since 4.4.0
998 998
 	 */
999
-	public function posts_where( $SQL, WP_Query $wp_query ) {
1000
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
1001
-		return EEH_Event_Query::posts_where( $SQL, $wp_query );
999
+	public function posts_where($SQL, WP_Query $wp_query) {
1000
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1001
+		return EEH_Event_Query::posts_where($SQL, $wp_query);
1002 1002
 	}
1003 1003
 	/**
1004 1004
 	 * 	@deprecated
1005 1005
 	 * 	@since 4.4.0
1006 1006
 	 */
1007
-	public static function posts_where_sql_for_show_expired( $show_expired = FALSE ) {
1008
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
1009
-		return EEH_Event_Query::posts_where_sql_for_show_expired( $show_expired );
1007
+	public static function posts_where_sql_for_show_expired($show_expired = FALSE) {
1008
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1009
+		return EEH_Event_Query::posts_where_sql_for_show_expired($show_expired);
1010 1010
 	}
1011 1011
 	/**
1012 1012
 	 * 	@deprecated
1013 1013
 	 * 	@since 4.4.0
1014 1014
 	 */
1015
-	public static function posts_where_sql_for_event_category_slug( $event_category_slug = NULL ) {
1016
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
1017
-		return EEH_Event_Query::posts_where_sql_for_event_category_slug( $event_category_slug );
1015
+	public static function posts_where_sql_for_event_category_slug($event_category_slug = NULL) {
1016
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1017
+		return EEH_Event_Query::posts_where_sql_for_event_category_slug($event_category_slug);
1018 1018
 	}
1019 1019
 	/**
1020 1020
 	 * 	@deprecated
1021 1021
 	 * 	@since 4.4.0
1022 1022
 	 */
1023
-	public static function posts_where_sql_for_event_list_month( $month = NULL ) {
1024
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
1025
-		return EEH_Event_Query::posts_where_sql_for_event_list_month( $month );
1023
+	public static function posts_where_sql_for_event_list_month($month = NULL) {
1024
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1025
+		return EEH_Event_Query::posts_where_sql_for_event_list_month($month);
1026 1026
 	}
1027 1027
 	/**
1028 1028
 	 * 	@deprecated
1029 1029
 	 * 	@since 4.4.0
1030 1030
 	 */
1031
-	public function posts_orderby( $SQL, WP_Query $wp_query ) {
1032
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
1033
-		return EEH_Event_Query::posts_orderby( $SQL, $wp_query );
1031
+	public function posts_orderby($SQL, WP_Query $wp_query) {
1032
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1033
+		return EEH_Event_Query::posts_orderby($SQL, $wp_query);
1034 1034
 	}
1035 1035
 	/**
1036 1036
 	 * 	@deprecated
1037 1037
 	 * 	@since 4.4.0
1038 1038
 	 */
1039
-	public static function posts_orderby_sql( $orderby_params = array(), $sort = 'ASC' ) {
1040
-		EED_Events_Archive::_doing_it_wrong_notice( __FUNCTION__ );
1041
-		return EEH_Event_Query::posts_orderby_sql( $orderby_params, $sort );
1039
+	public static function posts_orderby_sql($orderby_params = array(), $sort = 'ASC') {
1040
+		EED_Events_Archive::_doing_it_wrong_notice(__FUNCTION__);
1041
+		return EEH_Event_Query::posts_orderby_sql($orderby_params, $sort);
1042 1042
 	}
1043 1043
 
1044 1044
 
@@ -1069,8 +1069,8 @@  discard block
 block discarded – undo
1069 1069
  * @param string $extra_class
1070 1070
  * @return string
1071 1071
  */
1072
-function espresso_event_list_css( $extra_class = '' ) {
1073
-	return EED_Events_Archive::event_list_css( $extra_class );
1072
+function espresso_event_list_css($extra_class = '') {
1073
+	return EED_Events_Archive::event_list_css($extra_class);
1074 1074
 }
1075 1075
 
1076 1076
 /**
@@ -1084,14 +1084,14 @@  discard block
 block discarded – undo
1084 1084
  * @return bool
1085 1085
  */
1086 1086
 function espresso_display_full_description_in_event_list() {
1087
-	return EED_Events_Archive::display_description( 2 );
1087
+	return EED_Events_Archive::display_description(2);
1088 1088
 }
1089 1089
 
1090 1090
 /**
1091 1091
  * @return bool
1092 1092
  */
1093 1093
 function espresso_display_excerpt_in_event_list() {
1094
-	return EED_Events_Archive::display_description( 1 );
1094
+	return EED_Events_Archive::display_description(1);
1095 1095
 }
1096 1096
 
1097 1097
 /**
Please login to merge, or discard this patch.
core/CPTs/EE_Register_CPTs.core.php 1 patch
Indentation   +616 added lines, -616 removed lines patch added patch discarded remove patch
@@ -1,5 +1,5 @@  discard block
 block discarded – undo
1 1
 <?php if ( ! defined('EVENT_ESPRESSO_VERSION')) {
2
-    exit('No direct script access allowed');
2
+	exit('No direct script access allowed');
3 3
 }
4 4
 
5 5
 
@@ -14,604 +14,604 @@  discard block
 block discarded – undo
14 14
 class EE_Register_CPTs
15 15
 {
16 16
 
17
-    /**
18
-     * This property is used to hold an array of EE_default_term objects assigned to a custom post type when the post
19
-     * for that post type is published with no terms set for the taxonomy.
20
-     *
21
-     * @var array of EE_Default_Term objects
22
-     */
23
-    protected $_default_terms = array();
24
-
25
-
26
-
27
-    /**
28
-     *    constructor
29
-     * instantiated at init priority 5
30
-     */
31
-    public function __construct()
32
-    {
33
-        // register taxonomies
34
-        $taxonomies = self::get_taxonomies();
35
-        foreach ($taxonomies as $taxonomy => $tax) {
36
-            $this->register_taxonomy($taxonomy, $tax['singular_name'], $tax['plural_name'], $tax['args']);
37
-        }
38
-        // register CPTs
39
-        $CPTs = self::get_CPTs();
40
-        foreach ($CPTs as $CPT_name => $CPT) {
41
-            $this->register_CPT($CPT_name, $CPT['singular_name'], $CPT['plural_name'], $CPT['args'],
42
-                $CPT['singular_slug'], $CPT['plural_slug']);
43
-        }
44
-        // setup default terms in any of our taxonomies (but only if we're in admin).
45
-        // Why not added via register_activation_hook?
46
-        // Because it's possible that in future iterations of EE we may add new defaults for specialized taxonomies
47
-        // (think event_types) and register_activation_hook only reliably runs when a user manually activates the plugin.
48
-        // Keep in mind that this will READ these terms if they are deleted by the user.  Hence MUST use terms.
49
-        // if ( is_admin() ) {
50
-        // 	$this->set_must_use_event_types();
51
-        // }
52
-        //set default terms
53
-        $this->set_default_term('espresso_event_type', 'single-event', array('espresso_events'));
54
-        add_action('AHEE__EE_System__initialize_last', array(__CLASS__, 'maybe_flush_rewrite_rules'), 10);
55
-        // hook into save_post so that we can make sure that the default terms get saved on publish of registered cpts
56
-        // IF they don't have a term for that taxonomy set.
57
-        add_action('save_post', array($this, 'save_default_term'), 100, 2);
58
-        // remove no html restrictions from core wp saving of term descriptions.
59
-        // Note. this will affect only registered EE taxonomies.
60
-        $this->_allow_html_descriptions_for_ee_taxonomies();
61
-        do_action('AHEE__EE_Register_CPTs__construct_end', $this);
62
-    }
63
-
64
-
65
-
66
-    /**
67
-     * This will flush rewrite rules on demand.  This actually gets called around wp init priority level 100.
68
-     *
69
-     * @since 4.5.0
70
-     * @return void
71
-     */
72
-    public static function maybe_flush_rewrite_rules()
73
-    {
74
-        if (get_option('ee_flush_rewrite_rules', true)) {
75
-            flush_rewrite_rules();
76
-            update_option('ee_flush_rewrite_rules', false);
77
-        }
78
-    }
79
-
80
-
81
-
82
-    /**
83
-     * By default, WordPress strips all html from term taxonomy description content.  The purpose of this method is to
84
-     * remove that restriction and ensure that we still run ee term taxonomy descriptions through some full html
85
-     * sanitization equivalent to the post content field.
86
-     *
87
-     * @since 4.7.8
88
-     */
89
-    protected function _allow_html_descriptions_for_ee_taxonomies()
90
-    {
91
-        // first remove default filter for term description but we have to do this earlier
92
-        // before wp sets their own filter
93
-        // because they just set a global filter on all term descriptions before the custom term description filter.
94
-        // Really sux.
95
-        add_filter('pre_term_description', array($this, 'ee_filter_ee_term_description_not_wp'), 1, 2);
96
-    }
97
-
98
-
99
-
100
-    /**
101
-     * Callback for pre_term_description hook.
102
-     *
103
-     * @param string $description The description content.
104
-     * @param string $taxonomy    The taxonomy name for the taxonomy being filtered.
105
-     * @return string
106
-     */
107
-    public function ee_filter_ee_term_description_not_wp($description, $taxonomy)
108
-    {
109
-        //get a list of EE taxonomies
110
-        $ee_taxonomies = array_keys(self::get_taxonomies());
111
-        //only do our own thing if the taxonomy listed is an ee taxonomy.
112
-        if (in_array($taxonomy, $ee_taxonomies, true)) {
113
-            //remove default wp filter
114
-            remove_filter('pre_term_description', 'wp_filter_kses');
115
-            //sanitize THIS content.
116
-            $description = wp_kses($description, wp_kses_allowed_html('post'));
117
-        }
118
-        return $description;
119
-    }
120
-
121
-
122
-
123
-    /**
124
-     *    get_taxonomies
125
-     *
126
-     * @access    public
127
-     * @return    array
128
-     */
129
-    public static function get_taxonomies()
130
-    {
131
-        // define taxonomies
132
-        return apply_filters('FHEE__EE_Register_CPTs__get_taxonomies__taxonomies', array(
133
-            'espresso_event_categories' => array(
134
-                'singular_name' => __("Event Category", "event_espresso"),
135
-                'plural_name'   => __("Event Categories", "event_espresso"),
136
-                'args'          => array(
137
-                    'public'            => true,
138
-                    'show_in_nav_menus' => true,
139
-                    'show_in_rest'      => true,
140
-                    'capabilities'      => array(
141
-                        'manage_terms' => 'ee_manage_event_categories',
142
-                        'edit_terms'   => 'ee_edit_event_category',
143
-                        'delete_terms' => 'ee_delete_event_category',
144
-                        'assign_terms' => 'ee_assign_event_category',
145
-                    ),
146
-                    'rewrite'           => array('slug' => __('event-category', 'event_espresso')),
147
-                ),
148
-            ),
149
-            'espresso_venue_categories' => array(
150
-                'singular_name' => __("Venue Category", "event_espresso"),
151
-                'plural_name'   => __("Venue Categories", "event_espresso"),
152
-                'args'          => array(
153
-                    'public'            => true,
154
-                    'show_in_nav_menus' => false, //by default this doesn't show for decaf
155
-                    'show_in_rest'      => true,
156
-                    'capabilities'      => array(
157
-                        'manage_terms' => 'ee_manage_venue_categories',
158
-                        'edit_terms'   => 'ee_edit_venue_category',
159
-                        'delete_terms' => 'ee_delete_venue_category',
160
-                        'assign_terms' => 'ee_assign_venue_category',
161
-                    ),
162
-                    'rewrite'           => array('slug' => __('venue-category', 'event_espresso')),
163
-                ),
164
-            ),
165
-            'espresso_event_type'       => array(
166
-                'singular_name' => __("Event Type", "event_espresso"),
167
-                'plural_name'   => __("Event Types", "event_espresso"),
168
-                'args'          => array(
169
-                    'public'       => true,
170
-                    'show_ui'      => false,
171
-                    'show_in_rest' => true,
172
-                    'capabilities' => array(
173
-                        'manage_terms' => 'ee_read_event_type',
174
-                        'edit_terms'   => 'ee_edit_event_type',
175
-                        'delete_terms' => 'ee_delete_event_type',
176
-                        'assign_terms' => 'ee_assign_event_type',
177
-                    ),
178
-                    'rewrite'      => array('slug' => __('event-type', 'event_espresso')),
179
-                    'hierarchical' => true,
180
-                ),
181
-            ),
182
-        ));
183
-    }
184
-
185
-
186
-
187
-    /**
188
-     * This returns the corresponding model name for cpts registered by EE.
189
-     *
190
-     * @since 4.6.16.rc.000
191
-     * @param string $post_type_slug              If a slug is included, then attempt to retrieve the model name for
192
-     *                                            the given cpt slug.  Otherwise if empty, then we'll return all cpt
193
-     *                                            model names for cpts registered in EE.
194
-     * @return array           Empty array if no matching model names for the given slug or an array of model
195
-     *                                            names indexed by post type slug.
196
-     */
197
-    public static function get_cpt_model_names($post_type_slug = '')
198
-    {
199
-        $cpts = self::get_CPTs();
200
-        //first if slug passed in...
201
-        if ( ! empty($post_type_slug)) {
202
-            //match?
203
-            if (
204
-                ! isset($cpts[$post_type_slug])
205
-                || (isset($cpts[$post_type_slug]) && empty($cpts[$post_type_slug]['class_name']))
206
-            ) {
207
-                return array();
208
-            }
209
-            //k let's get the model name for this cpt.
210
-            return array($post_type_slug => str_replace('EE', 'EEM', $cpts[$post_type_slug]['class_name']));
211
-        }
212
-        //if we made it here then we're returning an array of cpt model names indexed by post_type_slug.
213
-        $cpt_models = array();
214
-        foreach ($cpts as $slug => $args) {
215
-            if ( ! empty($args['class_name'])) {
216
-                $cpt_models[$slug] = str_replace('EE', 'EEM', $args['class_name']);
217
-            }
218
-        }
219
-        return $cpt_models;
220
-    }
221
-
222
-
223
-
224
-    /**
225
-     * This instantiates cpt models related to the cpts registered via EE.
226
-     *
227
-     * @since 4.6.16.rc.000
228
-     * @param string $post_type_slug If valid slug is provided, then will instantiate the model only for
229
-     *                               the cpt matching the given slug.  Otherwise all cpt models will be
230
-     *                               instantiated (if possible).
231
-     * @return EEM_CPT_Base[]        successful instantiation will return an array of successfully instantiated
232
-     *                               EEM models indexed by post slug.
233
-     */
234
-    public static function instantiate_cpt_models($post_type_slug = '')
235
-    {
236
-        $cpt_model_names = self::get_cpt_model_names($post_type_slug);
237
-        $instantiated = array();
238
-        foreach ($cpt_model_names as $slug => $model_name) {
239
-            $instance = EE_Registry::instance()->load_model(str_replace('EEM_', '', $model_name));
240
-            if ($instance instanceof EEM_CPT_Base) {
241
-                $instantiated[$slug] = $instance;
242
-            }
243
-        }
244
-        return $instantiated;
245
-    }
246
-
247
-
248
-
249
-    /**
250
-     *    get_CPTs
251
-     *
252
-     * @access    public
253
-     * @return    array
254
-     */
255
-    public static function get_CPTs()
256
-    {
257
-        // define CPTs
258
-        // NOTE the ['args']['page_templates'] array index is something specific to our CPTs
259
-        // and not part of the WP custom post type api.
260
-        return apply_filters('FHEE__EE_Register_CPTs__get_CPTs__cpts', array(
261
-            'espresso_events'    => array(
262
-                'singular_name' => __("Event", "event_espresso"),
263
-                'plural_name'   => __("Events", "event_espresso"),
264
-                'singular_slug' => __("event", "event_espresso"),
265
-                'plural_slug'   => EE_Registry::instance()->CFG->core->event_cpt_slug,
266
-                'class_name'    => 'EE_Event',
267
-                'args'          => array(
268
-                    'public'            => true,
269
-                    'show_in_nav_menus' => true,
270
-                    'capability_type'   => 'event',
271
-                    'capabilities'      => array(
272
-                        'edit_post'              => 'ee_edit_event',
273
-                        'read_post'              => 'ee_read_event',
274
-                        'delete_post'            => 'ee_delete_event',
275
-                        'edit_posts'             => 'ee_edit_events',
276
-                        'edit_others_posts'      => 'ee_edit_others_events',
277
-                        'publish_posts'          => 'ee_publish_events',
278
-                        'read_private_posts'     => 'ee_read_private_events',
279
-                        'delete_posts'           => 'ee_delete_events',
280
-                        'delete_private_posts'   => 'ee_delete_private_events',
281
-                        'delete_published_posts' => 'ee_delete_published_events',
282
-                        'delete_others_posts'    => 'ee_delete_others_events',
283
-                        'edit_private_posts'     => 'ee_edit_private_events',
284
-                        'edit_published_posts'   => 'ee_edit_published_events',
285
-                    ),
286
-                    'taxonomies'        => array(
287
-                        'espresso_event_categories',
288
-                        'espresso_event_type',
289
-                        'post_tag',
290
-                    ),
291
-                    'page_templates'    => true,
292
-                ),
293
-            ),
294
-            'espresso_venues'    => array(
295
-                'singular_name' => __("Venue", "event_espresso"),
296
-                'plural_name'   => __("Venues", "event_espresso"),
297
-                'singular_slug' => __("venue", "event_espresso"),
298
-                'plural_slug'   => __("venues", "event_espresso"),
299
-                'class_name'    => 'EE_Venue',
300
-                'args'          => array(
301
-                    'public'            => true,
302
-                    'show_in_nav_menus' => false, //by default this doesn't show for decaf,
303
-                    'capability_type'   => 'venue',
304
-                    'capabilities'      => array(
305
-                        'edit_post'              => 'ee_edit_venue',
306
-                        'read_post'              => 'ee_read_venue',
307
-                        'delete_post'            => 'ee_delete_venue',
308
-                        'edit_posts'             => 'ee_edit_venues',
309
-                        'edit_others_posts'      => 'ee_edit_others_venues',
310
-                        'publish_posts'          => 'ee_publish_venues',
311
-                        'read_private_posts'     => 'ee_read_private_venues',
312
-                        'delete_posts'           => 'ee_delete_venues',
313
-                        'delete_private_posts'   => 'ee_delete_private_venues',
314
-                        'delete_published_posts' => 'ee_delete_published_venues',
315
-                        'delete_others_posts'    => 'ee_edit_others_venues',
316
-                        'edit_private_posts'     => 'ee_edit_private_venues',
317
-                        'edit_published_posts'   => 'ee_edit_published_venues',
318
-                    ),
319
-                    'taxonomies'        => array(
320
-                        'espresso_venue_categories',
321
-                        'post_tag',
322
-                    ),
323
-                    'page_templates'    => true,
324
-                ),
325
-            ),
326
-            'espresso_attendees' => array(
327
-                'singular_name' => __("Contact", "event_espresso"),
328
-                'plural_name'   => __("Contacts", "event_espresso"),
329
-                'singular_slug' => __("contact", "event_espresso"),
330
-                'plural_slug'   => __("contacts", "event_espresso"),
331
-                'class_name'    => 'EE_Attendee',
332
-                'args'          => array(
333
-                    'public'             => false,
334
-                    'publicly_queryable' => false,
335
-                    'hierarchical'       => false,
336
-                    'has_archive'        => false,
337
-                    'taxonomies'         => array('post_tag'),
338
-                    'capability_type'    => 'contact',
339
-                    'capabilities'       => array(
340
-                        'edit_post'              => 'ee_edit_contact',
341
-                        'read_post'              => 'ee_read_contact',
342
-                        'delete_post'            => 'ee_delete_contact',
343
-                        'edit_posts'             => 'ee_edit_contacts',
344
-                        'edit_others_posts'      => 'ee_edit_contacts',
345
-                        'publish_posts'          => 'ee_edit_contacts',
346
-                        'read_private_posts'     => 'ee_edit_contacts',
347
-                        'delete_posts'           => 'ee_delete_contacts',
348
-                        'delete_private_posts'   => 'ee_delete_contacts',
349
-                        'delete_published_posts' => 'ee_delete_contacts',
350
-                        'delete_others_posts'    => 'ee_delete_contacts',
351
-                        'edit_private_posts'     => 'ee_edit_contacts',
352
-                        'edit_published_posts'   => 'ee_edit_contacts',
353
-                    ),
354
-                    'supports'           => array('editor', 'thumbnail', 'excerpt', 'custom-fields', 'comments'),
355
-                ),
356
-            ),
357
-        ));
358
-    }
359
-
360
-
361
-
362
-    /**
363
-     * This basically goes through the CPT array and returns only CPT's
364
-     * that have the ['args']['public'] option set as false
365
-     *
366
-     * @return array
367
-     */
368
-    public static function get_private_CPTs()
369
-    {
370
-        $CPTs = self::get_CPTs();
371
-        $private_CPTs = array();
372
-        foreach ($CPTs as $CPT => $details) {
373
-            if (empty($details['args']['public'])) {
374
-                $private_CPTs[$CPT] = $details;
375
-            }
376
-        }
377
-        return $private_CPTs;
378
-    }
379
-
380
-
381
-
382
-    /**
383
-     * Registers a custom taxonomy. Should be called before registering custom post types,
384
-     * otherwise you should link the taxonomy to the custom post type using 'register_taxonomy_for_object_type'.
385
-     *
386
-     * @param string $taxonomy_name , eg 'books'
387
-     * @param string $singular_name internationalized singular name
388
-     * @param string $plural_name   internationalized plural name
389
-     * @param array  $override_args like $args on http://codex.wordpress.org/Function_Reference/register_taxonomy
390
-     */
391
-    public function register_taxonomy($taxonomy_name, $singular_name, $plural_name, $override_args = array())
392
-    {
393
-        $args = array(
394
-            'hierarchical'      => true,
395
-            'labels'            => array(
396
-                'name'          => $plural_name,
397
-                'singular_name' => $singular_name,
398
-            ),
399
-            'show_ui'           => true,
400
-            'show_ee_ui'        => true,
401
-            'show_admin_column' => true,
402
-            'query_var'         => true,
403
-            'show_in_nav_menus' => false,
404
-            'map_meta_cap'      => true
405
-            //'rewrite'           => array( 'slug' => 'genre' ),
406
-        );
407
-        if ($override_args) {
408
-            if (isset($override_args['labels'])) {
409
-                $labels = array_merge($args['labels'], $override_args['labels']);
410
-                $args['labels'] = $labels;
411
-            }
412
-            $args = array_merge($args, $override_args);
413
-        }
414
-        register_taxonomy($taxonomy_name, null, $args);
415
-    }
416
-
417
-
418
-
419
-    /**
420
-     * Registers a new custom post type. Sets default settings given only the following params.
421
-     *
422
-     * @param string $post_type     the actual post type name
423
-     *                              (VERY IMPORTANT: this much match what the slug is for admin pages related to this
424
-     *                              cpt Also any models must use this slug as well)
425
-     * @param string $singular_name a pre-internationalized string for the singular name of the objects
426
-     * @param string $plural_name   a pre-internalized string for the plural name of the objects
427
-     * @param array  $override_args exactly like $args as described in
428
-     *                              http://codex.wordpress.org/Function_Reference/register_post_type The default values
429
-     *                              set in this function will be overridden by whatever you set in $override_args
430
-     * @param string $singular_slug
431
-     * @param string $plural_slug
432
-     * @return void , but registers the custom post type
433
-     */
434
-    public function register_CPT(
435
-        $post_type,
436
-        $singular_name,
437
-        $plural_name,
438
-        $override_args = array(),
439
-        $singular_slug = '',
440
-        $plural_slug = ''
441
-    ) {
442
-        $labels = array(
443
-            'name'               => $plural_name,
444
-            'singular_name'      => $singular_name,
445
-            'singular_slug'      => $singular_slug,
446
-            'plural_slug'        => $plural_slug,
447
-            'add_new'            => sprintf(__("Add %s", "event_espresso"), $singular_name),
448
-            'add_new_item'       => sprintf(__("Add New %s", "event_espresso"), $singular_name),
449
-            'edit_item'          => sprintf(__("Edit %s", "event_espresso"), $singular_name),
450
-            'new_item'           => sprintf(__("New %s", "event_espresso"), $singular_name),
451
-            'all_items'          => sprintf(__("All %s", "event_espresso"), $plural_name),
452
-            'view_item'          => sprintf(__("View %s", "event_espresso"), $singular_name),
453
-            'search_items'       => sprintf(__("Search %s", "event_espresso"), $plural_name),
454
-            'not_found'          => sprintf(__("No %s found", "event_espresso"), $plural_name),
455
-            'not_found_in_trash' => sprintf(__("No %s found in Trash", "event_espresso"), $plural_name),
456
-            'parent_item_colon'  => '',
457
-            'menu_name'          => sprintf(__("%s", "event_espresso"), $plural_name),
458
-        );
459
-        //verify plural slug and singular slug, if they aren't we'll use $singular_name and $plural_name
460
-        // $singular_slug = ! empty($singular_slug) ? $singular_slug : $singular_name;
461
-        $plural_slug = ! empty($plural_slug) ? $plural_slug : $plural_name;
462
-        //note the page_templates arg in the supports index is something specific to EE.
463
-        //  WordPress doesn't actually have that in their register_post_type api.
464
-        $args = array(
465
-            'labels'             => $labels,
466
-            'public'             => true,
467
-            'publicly_queryable' => true,
468
-            'show_ui'            => false,
469
-            'show_ee_ui'         => true,
470
-            'show_in_menu'       => false,
471
-            'show_in_nav_menus'  => false,
472
-            'query_var'          => true,
473
-            'rewrite'            => apply_filters(
474
-                'FHEE__EE_Register_CPTs__register_CPT__rewrite',
475
-                array('slug' => $plural_slug),
476
-                $post_type
477
-            ),
478
-            'capability_type'    => 'post',
479
-            'map_meta_cap'       => true,
480
-            'has_archive'        => true,
481
-            'hierarchical'       => false,
482
-            'menu_position'      => null,
483
-            'supports'           => array(
484
-                'title',
485
-                'editor',
486
-                'author',
487
-                'thumbnail',
488
-                'excerpt',
489
-                'custom-fields',
490
-                'comments',
491
-            ),
492
-        );
493
-        if ($override_args) {
494
-            if (isset($override_args['labels'])) {
495
-                $labels = array_merge($args['labels'], $override_args['labels']);
496
-            }
497
-            $args = array_merge($args, $override_args);
498
-            $args['labels'] = $labels;
499
-        }
500
-        register_post_type($post_type, $args);
501
-    }
502
-
503
-
504
-
505
-    public function set_must_use_event_types()
506
-    {
507
-        $term_details = array(
508
-            //Attendee's register for the first date-time only
509
-            'single-event'    => array(
510
-                __('Single Event', 'event_espresso'),
511
-                __('A single event that spans one or more consecutive days.', 'event_espresso'),
512
-            ),
513
-            //example: a party or two-day long workshop
514
-            //Attendee's can register for any of the date-times
515
-            'multi-event'     => array(
516
-                __('Multi Event', 'event_espresso'),
517
-                __('Multiple, separate, but related events that occur on consecutive days.', 'event_espresso'),
518
-            ),
519
-            //example: a three day music festival or week long conference
520
-            //Attendee's register for the first date-time only
521
-            'event-series'    => array(
522
-                __('Event Series', 'event_espresso'),
523
-                __(' Multiple events that occur over multiple non-consecutive days.', 'event_espresso'),
524
-            ),
525
-            //example: an 8 week introduction to basket weaving course
526
-            //Attendee's can register for any of the date-times.
527
-            'recurring-event' => array(
528
-                __('Recurring Event', 'event_espresso'),
529
-                __('Multiple events that occur over multiple non-consecutive days.', 'event_espresso'),
530
-            ),
531
-            //example: a yoga class
532
-            'ongoing' => array(
533
-                __('Ongoing Event', 'event_espresso'),
534
-                __('An "event" that people can purchase tickets to gain access for anytime for this event regardless of date times on the event',
535
-                    'event_espresso'),
536
-            )
537
-            //example: access to a museum
538
-            //'walk-in' => array( __('Walk In', 'event_espresso'), __('Single datetime and single entry recurring events. Attendees register for one or multiple datetimes individually.', 'event_espresso') ),
539
-            //'reservation' => array( __('Reservation', 'event_espresso'), __('Reservations are created by specifying available datetimes and quantities. Attendees choose from the available datetimes and specify the quantity available (if the maximum is greater than 1)') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1
540
-            // 'multiple-session' => array( __('Multiple Session', 'event_espresso'), __('Multiple event, multiple datetime, hierarchically organized, custom entry events. Attendees may be required to register for a parent event before being allowed to register for child events. Attendees can register for any combination of child events as long as the datetimes do not conflict. Parent and child events may have additional fees or registration questions.') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1
541
-            //'appointment' => array( __('Appointments', 'event_espresso'), __('Time slotted events where datetimes are generally in hours or minutes. For example, attendees can register for a single 15 minute or 1 hour time slot and this type of availability frequently reoccurs.', 'event_espresso') )
542
-        );
543
-        $this->set_must_use_terms('espresso_event_type', $term_details);
544
-    }
545
-
546
-
547
-
548
-    /**
549
-     * wrapper method for handling the setting up of initial terms in the db (if they don't already exist).
550
-     * Note this should ONLY be used for terms that always must be present.  Be aware that if an initial term is
551
-     * deleted then it WILL be recreated.
552
-     *
553
-     * @param string $taxonomy     The name of the taxonomy
554
-     * @param array  $term_details An array of term details indexed by slug and containing Name of term, and
555
-     *                             description as the elements in the array
556
-     * @return void
557
-     */
558
-    public function set_must_use_terms($taxonomy, $term_details)
559
-    {
560
-        $term_details = (array)$term_details;
561
-        foreach ($term_details as $slug => $details) {
562
-            if ( ! term_exists($slug, $taxonomy)) {
563
-                $insert_arr = array(
564
-                    'slug'        => $slug,
565
-                    'description' => $details[1],
566
-                );
567
-                wp_insert_term($details[0], $taxonomy, $insert_arr);
568
-            }
569
-        }
570
-    }
571
-
572
-
573
-
574
-    /**
575
-     * Allows us to set what the default will be for terms when a cpt is PUBLISHED.
576
-     *
577
-     * @param string $taxonomy  The taxonomy we're using for the default term
578
-     * @param string $term_slug The slug of the term that will be the default.
579
-     * @param array  $cpt_slugs An array of custom post types we want the default assigned to
580
-     */
581
-    public function set_default_term($taxonomy, $term_slug, $cpt_slugs = array())
582
-    {
583
-        $this->_default_terms[][$term_slug] = new EE_Default_Term($taxonomy, $term_slug, $cpt_slugs);
584
-    }
585
-
586
-
587
-
588
-    /**
589
-     * hooked into the wp 'save_post' action hook for setting our default terms found in the $_default_terms property
590
-     *
591
-     * @param  int    $post_id ID of CPT being saved
592
-     * @param  object $post    Post object
593
-     * @return void
594
-     */
595
-    public function save_default_term($post_id, $post)
596
-    {
597
-        if (empty($this->_default_terms)) {
598
-            return;
599
-        } //no default terms set so lets just exit.
600
-        foreach ($this->_default_terms as $defaults) {
601
-            foreach ($defaults as $default_obj) {
602
-                if ($post->post_status === 'publish' && in_array($post->post_type, $default_obj->cpt_slugs, true)) {
603
-                    //note some error proofing going on here to save unnecessary db queries
604
-                    $taxonomies = get_object_taxonomies($post->post_type);
605
-                    foreach ((array)$taxonomies as $taxonomy) {
606
-                        $terms = wp_get_post_terms($post_id, $taxonomy);
607
-                        if (empty($terms) && $taxonomy === $default_obj->taxonomy) {
608
-                            wp_set_object_terms($post_id, array($default_obj->term_slug), $taxonomy);
609
-                        }
610
-                    }
611
-                }
612
-            }
613
-        }
614
-    }
17
+	/**
18
+	 * This property is used to hold an array of EE_default_term objects assigned to a custom post type when the post
19
+	 * for that post type is published with no terms set for the taxonomy.
20
+	 *
21
+	 * @var array of EE_Default_Term objects
22
+	 */
23
+	protected $_default_terms = array();
24
+
25
+
26
+
27
+	/**
28
+	 *    constructor
29
+	 * instantiated at init priority 5
30
+	 */
31
+	public function __construct()
32
+	{
33
+		// register taxonomies
34
+		$taxonomies = self::get_taxonomies();
35
+		foreach ($taxonomies as $taxonomy => $tax) {
36
+			$this->register_taxonomy($taxonomy, $tax['singular_name'], $tax['plural_name'], $tax['args']);
37
+		}
38
+		// register CPTs
39
+		$CPTs = self::get_CPTs();
40
+		foreach ($CPTs as $CPT_name => $CPT) {
41
+			$this->register_CPT($CPT_name, $CPT['singular_name'], $CPT['plural_name'], $CPT['args'],
42
+				$CPT['singular_slug'], $CPT['plural_slug']);
43
+		}
44
+		// setup default terms in any of our taxonomies (but only if we're in admin).
45
+		// Why not added via register_activation_hook?
46
+		// Because it's possible that in future iterations of EE we may add new defaults for specialized taxonomies
47
+		// (think event_types) and register_activation_hook only reliably runs when a user manually activates the plugin.
48
+		// Keep in mind that this will READ these terms if they are deleted by the user.  Hence MUST use terms.
49
+		// if ( is_admin() ) {
50
+		// 	$this->set_must_use_event_types();
51
+		// }
52
+		//set default terms
53
+		$this->set_default_term('espresso_event_type', 'single-event', array('espresso_events'));
54
+		add_action('AHEE__EE_System__initialize_last', array(__CLASS__, 'maybe_flush_rewrite_rules'), 10);
55
+		// hook into save_post so that we can make sure that the default terms get saved on publish of registered cpts
56
+		// IF they don't have a term for that taxonomy set.
57
+		add_action('save_post', array($this, 'save_default_term'), 100, 2);
58
+		// remove no html restrictions from core wp saving of term descriptions.
59
+		// Note. this will affect only registered EE taxonomies.
60
+		$this->_allow_html_descriptions_for_ee_taxonomies();
61
+		do_action('AHEE__EE_Register_CPTs__construct_end', $this);
62
+	}
63
+
64
+
65
+
66
+	/**
67
+	 * This will flush rewrite rules on demand.  This actually gets called around wp init priority level 100.
68
+	 *
69
+	 * @since 4.5.0
70
+	 * @return void
71
+	 */
72
+	public static function maybe_flush_rewrite_rules()
73
+	{
74
+		if (get_option('ee_flush_rewrite_rules', true)) {
75
+			flush_rewrite_rules();
76
+			update_option('ee_flush_rewrite_rules', false);
77
+		}
78
+	}
79
+
80
+
81
+
82
+	/**
83
+	 * By default, WordPress strips all html from term taxonomy description content.  The purpose of this method is to
84
+	 * remove that restriction and ensure that we still run ee term taxonomy descriptions through some full html
85
+	 * sanitization equivalent to the post content field.
86
+	 *
87
+	 * @since 4.7.8
88
+	 */
89
+	protected function _allow_html_descriptions_for_ee_taxonomies()
90
+	{
91
+		// first remove default filter for term description but we have to do this earlier
92
+		// before wp sets their own filter
93
+		// because they just set a global filter on all term descriptions before the custom term description filter.
94
+		// Really sux.
95
+		add_filter('pre_term_description', array($this, 'ee_filter_ee_term_description_not_wp'), 1, 2);
96
+	}
97
+
98
+
99
+
100
+	/**
101
+	 * Callback for pre_term_description hook.
102
+	 *
103
+	 * @param string $description The description content.
104
+	 * @param string $taxonomy    The taxonomy name for the taxonomy being filtered.
105
+	 * @return string
106
+	 */
107
+	public function ee_filter_ee_term_description_not_wp($description, $taxonomy)
108
+	{
109
+		//get a list of EE taxonomies
110
+		$ee_taxonomies = array_keys(self::get_taxonomies());
111
+		//only do our own thing if the taxonomy listed is an ee taxonomy.
112
+		if (in_array($taxonomy, $ee_taxonomies, true)) {
113
+			//remove default wp filter
114
+			remove_filter('pre_term_description', 'wp_filter_kses');
115
+			//sanitize THIS content.
116
+			$description = wp_kses($description, wp_kses_allowed_html('post'));
117
+		}
118
+		return $description;
119
+	}
120
+
121
+
122
+
123
+	/**
124
+	 *    get_taxonomies
125
+	 *
126
+	 * @access    public
127
+	 * @return    array
128
+	 */
129
+	public static function get_taxonomies()
130
+	{
131
+		// define taxonomies
132
+		return apply_filters('FHEE__EE_Register_CPTs__get_taxonomies__taxonomies', array(
133
+			'espresso_event_categories' => array(
134
+				'singular_name' => __("Event Category", "event_espresso"),
135
+				'plural_name'   => __("Event Categories", "event_espresso"),
136
+				'args'          => array(
137
+					'public'            => true,
138
+					'show_in_nav_menus' => true,
139
+					'show_in_rest'      => true,
140
+					'capabilities'      => array(
141
+						'manage_terms' => 'ee_manage_event_categories',
142
+						'edit_terms'   => 'ee_edit_event_category',
143
+						'delete_terms' => 'ee_delete_event_category',
144
+						'assign_terms' => 'ee_assign_event_category',
145
+					),
146
+					'rewrite'           => array('slug' => __('event-category', 'event_espresso')),
147
+				),
148
+			),
149
+			'espresso_venue_categories' => array(
150
+				'singular_name' => __("Venue Category", "event_espresso"),
151
+				'plural_name'   => __("Venue Categories", "event_espresso"),
152
+				'args'          => array(
153
+					'public'            => true,
154
+					'show_in_nav_menus' => false, //by default this doesn't show for decaf
155
+					'show_in_rest'      => true,
156
+					'capabilities'      => array(
157
+						'manage_terms' => 'ee_manage_venue_categories',
158
+						'edit_terms'   => 'ee_edit_venue_category',
159
+						'delete_terms' => 'ee_delete_venue_category',
160
+						'assign_terms' => 'ee_assign_venue_category',
161
+					),
162
+					'rewrite'           => array('slug' => __('venue-category', 'event_espresso')),
163
+				),
164
+			),
165
+			'espresso_event_type'       => array(
166
+				'singular_name' => __("Event Type", "event_espresso"),
167
+				'plural_name'   => __("Event Types", "event_espresso"),
168
+				'args'          => array(
169
+					'public'       => true,
170
+					'show_ui'      => false,
171
+					'show_in_rest' => true,
172
+					'capabilities' => array(
173
+						'manage_terms' => 'ee_read_event_type',
174
+						'edit_terms'   => 'ee_edit_event_type',
175
+						'delete_terms' => 'ee_delete_event_type',
176
+						'assign_terms' => 'ee_assign_event_type',
177
+					),
178
+					'rewrite'      => array('slug' => __('event-type', 'event_espresso')),
179
+					'hierarchical' => true,
180
+				),
181
+			),
182
+		));
183
+	}
184
+
185
+
186
+
187
+	/**
188
+	 * This returns the corresponding model name for cpts registered by EE.
189
+	 *
190
+	 * @since 4.6.16.rc.000
191
+	 * @param string $post_type_slug              If a slug is included, then attempt to retrieve the model name for
192
+	 *                                            the given cpt slug.  Otherwise if empty, then we'll return all cpt
193
+	 *                                            model names for cpts registered in EE.
194
+	 * @return array           Empty array if no matching model names for the given slug or an array of model
195
+	 *                                            names indexed by post type slug.
196
+	 */
197
+	public static function get_cpt_model_names($post_type_slug = '')
198
+	{
199
+		$cpts = self::get_CPTs();
200
+		//first if slug passed in...
201
+		if ( ! empty($post_type_slug)) {
202
+			//match?
203
+			if (
204
+				! isset($cpts[$post_type_slug])
205
+				|| (isset($cpts[$post_type_slug]) && empty($cpts[$post_type_slug]['class_name']))
206
+			) {
207
+				return array();
208
+			}
209
+			//k let's get the model name for this cpt.
210
+			return array($post_type_slug => str_replace('EE', 'EEM', $cpts[$post_type_slug]['class_name']));
211
+		}
212
+		//if we made it here then we're returning an array of cpt model names indexed by post_type_slug.
213
+		$cpt_models = array();
214
+		foreach ($cpts as $slug => $args) {
215
+			if ( ! empty($args['class_name'])) {
216
+				$cpt_models[$slug] = str_replace('EE', 'EEM', $args['class_name']);
217
+			}
218
+		}
219
+		return $cpt_models;
220
+	}
221
+
222
+
223
+
224
+	/**
225
+	 * This instantiates cpt models related to the cpts registered via EE.
226
+	 *
227
+	 * @since 4.6.16.rc.000
228
+	 * @param string $post_type_slug If valid slug is provided, then will instantiate the model only for
229
+	 *                               the cpt matching the given slug.  Otherwise all cpt models will be
230
+	 *                               instantiated (if possible).
231
+	 * @return EEM_CPT_Base[]        successful instantiation will return an array of successfully instantiated
232
+	 *                               EEM models indexed by post slug.
233
+	 */
234
+	public static function instantiate_cpt_models($post_type_slug = '')
235
+	{
236
+		$cpt_model_names = self::get_cpt_model_names($post_type_slug);
237
+		$instantiated = array();
238
+		foreach ($cpt_model_names as $slug => $model_name) {
239
+			$instance = EE_Registry::instance()->load_model(str_replace('EEM_', '', $model_name));
240
+			if ($instance instanceof EEM_CPT_Base) {
241
+				$instantiated[$slug] = $instance;
242
+			}
243
+		}
244
+		return $instantiated;
245
+	}
246
+
247
+
248
+
249
+	/**
250
+	 *    get_CPTs
251
+	 *
252
+	 * @access    public
253
+	 * @return    array
254
+	 */
255
+	public static function get_CPTs()
256
+	{
257
+		// define CPTs
258
+		// NOTE the ['args']['page_templates'] array index is something specific to our CPTs
259
+		// and not part of the WP custom post type api.
260
+		return apply_filters('FHEE__EE_Register_CPTs__get_CPTs__cpts', array(
261
+			'espresso_events'    => array(
262
+				'singular_name' => __("Event", "event_espresso"),
263
+				'plural_name'   => __("Events", "event_espresso"),
264
+				'singular_slug' => __("event", "event_espresso"),
265
+				'plural_slug'   => EE_Registry::instance()->CFG->core->event_cpt_slug,
266
+				'class_name'    => 'EE_Event',
267
+				'args'          => array(
268
+					'public'            => true,
269
+					'show_in_nav_menus' => true,
270
+					'capability_type'   => 'event',
271
+					'capabilities'      => array(
272
+						'edit_post'              => 'ee_edit_event',
273
+						'read_post'              => 'ee_read_event',
274
+						'delete_post'            => 'ee_delete_event',
275
+						'edit_posts'             => 'ee_edit_events',
276
+						'edit_others_posts'      => 'ee_edit_others_events',
277
+						'publish_posts'          => 'ee_publish_events',
278
+						'read_private_posts'     => 'ee_read_private_events',
279
+						'delete_posts'           => 'ee_delete_events',
280
+						'delete_private_posts'   => 'ee_delete_private_events',
281
+						'delete_published_posts' => 'ee_delete_published_events',
282
+						'delete_others_posts'    => 'ee_delete_others_events',
283
+						'edit_private_posts'     => 'ee_edit_private_events',
284
+						'edit_published_posts'   => 'ee_edit_published_events',
285
+					),
286
+					'taxonomies'        => array(
287
+						'espresso_event_categories',
288
+						'espresso_event_type',
289
+						'post_tag',
290
+					),
291
+					'page_templates'    => true,
292
+				),
293
+			),
294
+			'espresso_venues'    => array(
295
+				'singular_name' => __("Venue", "event_espresso"),
296
+				'plural_name'   => __("Venues", "event_espresso"),
297
+				'singular_slug' => __("venue", "event_espresso"),
298
+				'plural_slug'   => __("venues", "event_espresso"),
299
+				'class_name'    => 'EE_Venue',
300
+				'args'          => array(
301
+					'public'            => true,
302
+					'show_in_nav_menus' => false, //by default this doesn't show for decaf,
303
+					'capability_type'   => 'venue',
304
+					'capabilities'      => array(
305
+						'edit_post'              => 'ee_edit_venue',
306
+						'read_post'              => 'ee_read_venue',
307
+						'delete_post'            => 'ee_delete_venue',
308
+						'edit_posts'             => 'ee_edit_venues',
309
+						'edit_others_posts'      => 'ee_edit_others_venues',
310
+						'publish_posts'          => 'ee_publish_venues',
311
+						'read_private_posts'     => 'ee_read_private_venues',
312
+						'delete_posts'           => 'ee_delete_venues',
313
+						'delete_private_posts'   => 'ee_delete_private_venues',
314
+						'delete_published_posts' => 'ee_delete_published_venues',
315
+						'delete_others_posts'    => 'ee_edit_others_venues',
316
+						'edit_private_posts'     => 'ee_edit_private_venues',
317
+						'edit_published_posts'   => 'ee_edit_published_venues',
318
+					),
319
+					'taxonomies'        => array(
320
+						'espresso_venue_categories',
321
+						'post_tag',
322
+					),
323
+					'page_templates'    => true,
324
+				),
325
+			),
326
+			'espresso_attendees' => array(
327
+				'singular_name' => __("Contact", "event_espresso"),
328
+				'plural_name'   => __("Contacts", "event_espresso"),
329
+				'singular_slug' => __("contact", "event_espresso"),
330
+				'plural_slug'   => __("contacts", "event_espresso"),
331
+				'class_name'    => 'EE_Attendee',
332
+				'args'          => array(
333
+					'public'             => false,
334
+					'publicly_queryable' => false,
335
+					'hierarchical'       => false,
336
+					'has_archive'        => false,
337
+					'taxonomies'         => array('post_tag'),
338
+					'capability_type'    => 'contact',
339
+					'capabilities'       => array(
340
+						'edit_post'              => 'ee_edit_contact',
341
+						'read_post'              => 'ee_read_contact',
342
+						'delete_post'            => 'ee_delete_contact',
343
+						'edit_posts'             => 'ee_edit_contacts',
344
+						'edit_others_posts'      => 'ee_edit_contacts',
345
+						'publish_posts'          => 'ee_edit_contacts',
346
+						'read_private_posts'     => 'ee_edit_contacts',
347
+						'delete_posts'           => 'ee_delete_contacts',
348
+						'delete_private_posts'   => 'ee_delete_contacts',
349
+						'delete_published_posts' => 'ee_delete_contacts',
350
+						'delete_others_posts'    => 'ee_delete_contacts',
351
+						'edit_private_posts'     => 'ee_edit_contacts',
352
+						'edit_published_posts'   => 'ee_edit_contacts',
353
+					),
354
+					'supports'           => array('editor', 'thumbnail', 'excerpt', 'custom-fields', 'comments'),
355
+				),
356
+			),
357
+		));
358
+	}
359
+
360
+
361
+
362
+	/**
363
+	 * This basically goes through the CPT array and returns only CPT's
364
+	 * that have the ['args']['public'] option set as false
365
+	 *
366
+	 * @return array
367
+	 */
368
+	public static function get_private_CPTs()
369
+	{
370
+		$CPTs = self::get_CPTs();
371
+		$private_CPTs = array();
372
+		foreach ($CPTs as $CPT => $details) {
373
+			if (empty($details['args']['public'])) {
374
+				$private_CPTs[$CPT] = $details;
375
+			}
376
+		}
377
+		return $private_CPTs;
378
+	}
379
+
380
+
381
+
382
+	/**
383
+	 * Registers a custom taxonomy. Should be called before registering custom post types,
384
+	 * otherwise you should link the taxonomy to the custom post type using 'register_taxonomy_for_object_type'.
385
+	 *
386
+	 * @param string $taxonomy_name , eg 'books'
387
+	 * @param string $singular_name internationalized singular name
388
+	 * @param string $plural_name   internationalized plural name
389
+	 * @param array  $override_args like $args on http://codex.wordpress.org/Function_Reference/register_taxonomy
390
+	 */
391
+	public function register_taxonomy($taxonomy_name, $singular_name, $plural_name, $override_args = array())
392
+	{
393
+		$args = array(
394
+			'hierarchical'      => true,
395
+			'labels'            => array(
396
+				'name'          => $plural_name,
397
+				'singular_name' => $singular_name,
398
+			),
399
+			'show_ui'           => true,
400
+			'show_ee_ui'        => true,
401
+			'show_admin_column' => true,
402
+			'query_var'         => true,
403
+			'show_in_nav_menus' => false,
404
+			'map_meta_cap'      => true
405
+			//'rewrite'           => array( 'slug' => 'genre' ),
406
+		);
407
+		if ($override_args) {
408
+			if (isset($override_args['labels'])) {
409
+				$labels = array_merge($args['labels'], $override_args['labels']);
410
+				$args['labels'] = $labels;
411
+			}
412
+			$args = array_merge($args, $override_args);
413
+		}
414
+		register_taxonomy($taxonomy_name, null, $args);
415
+	}
416
+
417
+
418
+
419
+	/**
420
+	 * Registers a new custom post type. Sets default settings given only the following params.
421
+	 *
422
+	 * @param string $post_type     the actual post type name
423
+	 *                              (VERY IMPORTANT: this much match what the slug is for admin pages related to this
424
+	 *                              cpt Also any models must use this slug as well)
425
+	 * @param string $singular_name a pre-internationalized string for the singular name of the objects
426
+	 * @param string $plural_name   a pre-internalized string for the plural name of the objects
427
+	 * @param array  $override_args exactly like $args as described in
428
+	 *                              http://codex.wordpress.org/Function_Reference/register_post_type The default values
429
+	 *                              set in this function will be overridden by whatever you set in $override_args
430
+	 * @param string $singular_slug
431
+	 * @param string $plural_slug
432
+	 * @return void , but registers the custom post type
433
+	 */
434
+	public function register_CPT(
435
+		$post_type,
436
+		$singular_name,
437
+		$plural_name,
438
+		$override_args = array(),
439
+		$singular_slug = '',
440
+		$plural_slug = ''
441
+	) {
442
+		$labels = array(
443
+			'name'               => $plural_name,
444
+			'singular_name'      => $singular_name,
445
+			'singular_slug'      => $singular_slug,
446
+			'plural_slug'        => $plural_slug,
447
+			'add_new'            => sprintf(__("Add %s", "event_espresso"), $singular_name),
448
+			'add_new_item'       => sprintf(__("Add New %s", "event_espresso"), $singular_name),
449
+			'edit_item'          => sprintf(__("Edit %s", "event_espresso"), $singular_name),
450
+			'new_item'           => sprintf(__("New %s", "event_espresso"), $singular_name),
451
+			'all_items'          => sprintf(__("All %s", "event_espresso"), $plural_name),
452
+			'view_item'          => sprintf(__("View %s", "event_espresso"), $singular_name),
453
+			'search_items'       => sprintf(__("Search %s", "event_espresso"), $plural_name),
454
+			'not_found'          => sprintf(__("No %s found", "event_espresso"), $plural_name),
455
+			'not_found_in_trash' => sprintf(__("No %s found in Trash", "event_espresso"), $plural_name),
456
+			'parent_item_colon'  => '',
457
+			'menu_name'          => sprintf(__("%s", "event_espresso"), $plural_name),
458
+		);
459
+		//verify plural slug and singular slug, if they aren't we'll use $singular_name and $plural_name
460
+		// $singular_slug = ! empty($singular_slug) ? $singular_slug : $singular_name;
461
+		$plural_slug = ! empty($plural_slug) ? $plural_slug : $plural_name;
462
+		//note the page_templates arg in the supports index is something specific to EE.
463
+		//  WordPress doesn't actually have that in their register_post_type api.
464
+		$args = array(
465
+			'labels'             => $labels,
466
+			'public'             => true,
467
+			'publicly_queryable' => true,
468
+			'show_ui'            => false,
469
+			'show_ee_ui'         => true,
470
+			'show_in_menu'       => false,
471
+			'show_in_nav_menus'  => false,
472
+			'query_var'          => true,
473
+			'rewrite'            => apply_filters(
474
+				'FHEE__EE_Register_CPTs__register_CPT__rewrite',
475
+				array('slug' => $plural_slug),
476
+				$post_type
477
+			),
478
+			'capability_type'    => 'post',
479
+			'map_meta_cap'       => true,
480
+			'has_archive'        => true,
481
+			'hierarchical'       => false,
482
+			'menu_position'      => null,
483
+			'supports'           => array(
484
+				'title',
485
+				'editor',
486
+				'author',
487
+				'thumbnail',
488
+				'excerpt',
489
+				'custom-fields',
490
+				'comments',
491
+			),
492
+		);
493
+		if ($override_args) {
494
+			if (isset($override_args['labels'])) {
495
+				$labels = array_merge($args['labels'], $override_args['labels']);
496
+			}
497
+			$args = array_merge($args, $override_args);
498
+			$args['labels'] = $labels;
499
+		}
500
+		register_post_type($post_type, $args);
501
+	}
502
+
503
+
504
+
505
+	public function set_must_use_event_types()
506
+	{
507
+		$term_details = array(
508
+			//Attendee's register for the first date-time only
509
+			'single-event'    => array(
510
+				__('Single Event', 'event_espresso'),
511
+				__('A single event that spans one or more consecutive days.', 'event_espresso'),
512
+			),
513
+			//example: a party or two-day long workshop
514
+			//Attendee's can register for any of the date-times
515
+			'multi-event'     => array(
516
+				__('Multi Event', 'event_espresso'),
517
+				__('Multiple, separate, but related events that occur on consecutive days.', 'event_espresso'),
518
+			),
519
+			//example: a three day music festival or week long conference
520
+			//Attendee's register for the first date-time only
521
+			'event-series'    => array(
522
+				__('Event Series', 'event_espresso'),
523
+				__(' Multiple events that occur over multiple non-consecutive days.', 'event_espresso'),
524
+			),
525
+			//example: an 8 week introduction to basket weaving course
526
+			//Attendee's can register for any of the date-times.
527
+			'recurring-event' => array(
528
+				__('Recurring Event', 'event_espresso'),
529
+				__('Multiple events that occur over multiple non-consecutive days.', 'event_espresso'),
530
+			),
531
+			//example: a yoga class
532
+			'ongoing' => array(
533
+				__('Ongoing Event', 'event_espresso'),
534
+				__('An "event" that people can purchase tickets to gain access for anytime for this event regardless of date times on the event',
535
+					'event_espresso'),
536
+			)
537
+			//example: access to a museum
538
+			//'walk-in' => array( __('Walk In', 'event_espresso'), __('Single datetime and single entry recurring events. Attendees register for one or multiple datetimes individually.', 'event_espresso') ),
539
+			//'reservation' => array( __('Reservation', 'event_espresso'), __('Reservations are created by specifying available datetimes and quantities. Attendees choose from the available datetimes and specify the quantity available (if the maximum is greater than 1)') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1
540
+			// 'multiple-session' => array( __('Multiple Session', 'event_espresso'), __('Multiple event, multiple datetime, hierarchically organized, custom entry events. Attendees may be required to register for a parent event before being allowed to register for child events. Attendees can register for any combination of child events as long as the datetimes do not conflict. Parent and child events may have additional fees or registration questions.') ), //@TODO to avoid confusion we'll implement this in a later iteration > EE4.1
541
+			//'appointment' => array( __('Appointments', 'event_espresso'), __('Time slotted events where datetimes are generally in hours or minutes. For example, attendees can register for a single 15 minute or 1 hour time slot and this type of availability frequently reoccurs.', 'event_espresso') )
542
+		);
543
+		$this->set_must_use_terms('espresso_event_type', $term_details);
544
+	}
545
+
546
+
547
+
548
+	/**
549
+	 * wrapper method for handling the setting up of initial terms in the db (if they don't already exist).
550
+	 * Note this should ONLY be used for terms that always must be present.  Be aware that if an initial term is
551
+	 * deleted then it WILL be recreated.
552
+	 *
553
+	 * @param string $taxonomy     The name of the taxonomy
554
+	 * @param array  $term_details An array of term details indexed by slug and containing Name of term, and
555
+	 *                             description as the elements in the array
556
+	 * @return void
557
+	 */
558
+	public function set_must_use_terms($taxonomy, $term_details)
559
+	{
560
+		$term_details = (array)$term_details;
561
+		foreach ($term_details as $slug => $details) {
562
+			if ( ! term_exists($slug, $taxonomy)) {
563
+				$insert_arr = array(
564
+					'slug'        => $slug,
565
+					'description' => $details[1],
566
+				);
567
+				wp_insert_term($details[0], $taxonomy, $insert_arr);
568
+			}
569
+		}
570
+	}
571
+
572
+
573
+
574
+	/**
575
+	 * Allows us to set what the default will be for terms when a cpt is PUBLISHED.
576
+	 *
577
+	 * @param string $taxonomy  The taxonomy we're using for the default term
578
+	 * @param string $term_slug The slug of the term that will be the default.
579
+	 * @param array  $cpt_slugs An array of custom post types we want the default assigned to
580
+	 */
581
+	public function set_default_term($taxonomy, $term_slug, $cpt_slugs = array())
582
+	{
583
+		$this->_default_terms[][$term_slug] = new EE_Default_Term($taxonomy, $term_slug, $cpt_slugs);
584
+	}
585
+
586
+
587
+
588
+	/**
589
+	 * hooked into the wp 'save_post' action hook for setting our default terms found in the $_default_terms property
590
+	 *
591
+	 * @param  int    $post_id ID of CPT being saved
592
+	 * @param  object $post    Post object
593
+	 * @return void
594
+	 */
595
+	public function save_default_term($post_id, $post)
596
+	{
597
+		if (empty($this->_default_terms)) {
598
+			return;
599
+		} //no default terms set so lets just exit.
600
+		foreach ($this->_default_terms as $defaults) {
601
+			foreach ($defaults as $default_obj) {
602
+				if ($post->post_status === 'publish' && in_array($post->post_type, $default_obj->cpt_slugs, true)) {
603
+					//note some error proofing going on here to save unnecessary db queries
604
+					$taxonomies = get_object_taxonomies($post->post_type);
605
+					foreach ((array)$taxonomies as $taxonomy) {
606
+						$terms = wp_get_post_terms($post_id, $taxonomy);
607
+						if (empty($terms) && $taxonomy === $default_obj->taxonomy) {
608
+							wp_set_object_terms($post_id, array($default_obj->term_slug), $taxonomy);
609
+						}
610
+					}
611
+				}
612
+			}
613
+		}
614
+	}
615 615
 
616 616
 }
617 617
 
@@ -625,27 +625,27 @@  discard block
 block discarded – undo
625 625
 {
626 626
 
627 627
 
628
-    //props holding the items
629
-    public $taxonomy  = '';
628
+	//props holding the items
629
+	public $taxonomy  = '';
630 630
 
631
-    public $cpt_slugs = array();
631
+	public $cpt_slugs = array();
632 632
 
633
-    public $term_slug = '';
633
+	public $term_slug = '';
634 634
 
635 635
 
636 636
 
637
-    /**
638
-     * constructor
639
-     *
640
-     * @param string $taxonomy  The taxonomy the default term belongs to
641
-     * @param string $term_slug The slug of the term that will be the default.
642
-     * @param array  $cpt_slugs The custom post type the default term gets saved with
643
-     */
644
-    public function __construct($taxonomy, $term_slug, $cpt_slugs = array())
645
-    {
646
-        $this->taxonomy = $taxonomy;
647
-        $this->cpt_slugs = (array)$cpt_slugs;
648
-        $this->term_slug = $term_slug;
649
-    }
637
+	/**
638
+	 * constructor
639
+	 *
640
+	 * @param string $taxonomy  The taxonomy the default term belongs to
641
+	 * @param string $term_slug The slug of the term that will be the default.
642
+	 * @param array  $cpt_slugs The custom post type the default term gets saved with
643
+	 */
644
+	public function __construct($taxonomy, $term_slug, $cpt_slugs = array())
645
+	{
646
+		$this->taxonomy = $taxonomy;
647
+		$this->cpt_slugs = (array)$cpt_slugs;
648
+		$this->term_slug = $term_slug;
649
+	}
650 650
 
651 651
 }
Please login to merge, or discard this patch.
core/libraries/payment_methods/EE_Payment_Method_Manager.lib.php 1 patch
Indentation   +419 added lines, -419 removed lines patch added patch discarded remove patch
@@ -19,420 +19,420 @@  discard block
 block discarded – undo
19 19
 class EE_Payment_Method_Manager implements ResettableInterface
20 20
 {
21 21
 
22
-    /**
23
-     * @var EE_Payment_Method_Manager $_instance
24
-     */
25
-    private static $_instance;
26
-
27
-    /**
28
-     * @var array keys are class names without 'EE_PMT_', values are their filepaths
29
-     */
30
-    protected $_payment_method_types = array();
31
-
32
-
33
-
34
-    /**
35
-     * @singleton method used to instantiate class object
36
-     * @return EE_Payment_Method_Manager instance
37
-     */
38
-    public static function instance()
39
-    {
40
-        // check if class object is instantiated, and instantiated properly
41
-        if (! self::$_instance instanceof EE_Payment_Method_Manager) {
42
-            self::$_instance = new self();
43
-        }
44
-        EE_Registry::instance()->load_lib('PMT_Base');
45
-        return self::$_instance;
46
-    }
47
-
48
-
49
-
50
-    /**
51
-     * Resets the instance and returns a new one
52
-     *
53
-     * @return EE_Payment_Method_Manager
54
-     */
55
-    public static function reset()
56
-    {
57
-        self::$_instance = null;
58
-        return self::instance();
59
-    }
60
-
61
-
62
-
63
-    /**
64
-     * If necessary, re-register payment methods
65
-     *
66
-     * @param boolean $force_recheck whether to recheck for payment method types,
67
-     *                               or just re-use the PMTs we found last time we checked during this request (if
68
-     *                               we have not yet checked during this request, then we need to check anyways)
69
-     */
70
-    public function maybe_register_payment_methods($force_recheck = false)
71
-    {
72
-        if (! $this->_payment_method_types || $force_recheck) {
73
-            $this->_register_payment_methods();
74
-            //if in admin lets ensure caps are set.
75
-            if (is_admin()) {
76
-                add_filter('FHEE__EE_Capabilities__init_caps_map__caps', array($this, 'add_payment_method_caps'));
77
-                EE_Registry::instance()->CAP->init_caps();
78
-            }
79
-        }
80
-    }
81
-
82
-
83
-
84
-    /**
85
-     * register_payment_methods
86
-     *
87
-     * @return array
88
-     */
89
-    protected function _register_payment_methods()
90
-    {
91
-        // grab list of installed modules
92
-        $pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR);
93
-        // filter list of modules to register
94
-        $pm_to_register = apply_filters(
95
-            'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
96
-            $pm_to_register
97
-        );
98
-        // loop through folders
99
-        foreach ($pm_to_register as $pm_path) {
100
-            $this->register_payment_method($pm_path);
101
-        }
102
-        do_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods');
103
-        // filter list of installed modules
104
-        //keep them organized alphabetically by the payment method type's name
105
-        ksort($this->_payment_method_types);
106
-        return apply_filters(
107
-            'FHEE__EE_Payment_Method_Manager__register_payment_methods__installed_payment_methods',
108
-            $this->_payment_method_types
109
-        );
110
-    }
111
-
112
-
113
-
114
-    /**
115
-     * register_payment_method- makes core aware of this payment method
116
-     *
117
-     * @param string $payment_method_path - full path up to and including payment method folder
118
-     * @return boolean
119
-     */
120
-    public function register_payment_method($payment_method_path = '')
121
-    {
122
-        do_action('AHEE__EE_Payment_Method_Manager__register_payment_method__begin', $payment_method_path);
123
-        $module_ext = '.pm.php';
124
-        // make all separators match
125
-        $payment_method_path = rtrim(str_replace('/\\', DS, $payment_method_path), DS);
126
-        // grab and sanitize module name
127
-        $module_dir = basename($payment_method_path);
128
-        // create classname from module directory name
129
-        $module = str_replace(array('_', ' '), array(' ', '_'), $module_dir);
130
-        // add class prefix
131
-        $module_class = 'EE_PMT_' . $module;
132
-        // does the module exist ?
133
-        if (! is_readable($payment_method_path . DS . $module_class . $module_ext)) {
134
-            $msg = sprintf(
135
-                esc_html__(
136
-                    'The requested %s payment method file could not be found or is not readable due to file permissions.',
137
-                    'event_espresso'
138
-                ), $module
139
-            );
140
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
141
-            return false;
142
-        }
143
-        // load the module class file
144
-        require_once($payment_method_path . DS . $module_class . $module_ext);
145
-        // verify that class exists
146
-        if (! class_exists($module_class)) {
147
-            $msg = sprintf(
148
-                esc_html__('The requested %s module class does not exist.', 'event_espresso'),
149
-                $module_class
150
-            );
151
-            EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
152
-            return false;
153
-        }
154
-        // add to array of registered modules
155
-        $this->_payment_method_types[$module] = $payment_method_path . DS . $module_class . $module_ext;
156
-        return true;
157
-    }
158
-
159
-
160
-
161
-    /**
162
-     * Checks if a payment method has been registered, and if so includes it
163
-     *
164
-     * @param string  $payment_method_name like 'PayPal_Pro', (ie classname without the prefix 'EEPM_')
165
-     * @param boolean $force_recheck       whether to force re-checking for new payment method types
166
-     * @return boolean
167
-     */
168
-    public function payment_method_type_exists($payment_method_name, $force_recheck = false)
169
-    {
170
-        if (
171
-            $force_recheck
172
-            || ! is_array($this->_payment_method_types)
173
-            || ! isset($this->_payment_method_types[$payment_method_name])
174
-        ) {
175
-            $this->maybe_register_payment_methods($force_recheck);
176
-        }
177
-        if (isset($this->_payment_method_types[$payment_method_name])) {
178
-            require_once($this->_payment_method_types[$payment_method_name]);
179
-            return true;
180
-        }
181
-        return false;
182
-    }
183
-
184
-
185
-
186
-    /**
187
-     * Returns all the class names of the various payment method types
188
-     *
189
-     * @param boolean $with_prefixes TRUE: get payment method type class names; false just their 'names'
190
-     *                               (what you'd find in wp_esp_payment_method.PMD_type)
191
-     * @param boolean $force_recheck whether to force re-checking for new payment method types
192
-     * @return array
193
-     */
194
-    public function payment_method_type_names($with_prefixes = false, $force_recheck = false)
195
-    {
196
-        $this->maybe_register_payment_methods($force_recheck);
197
-        if ($with_prefixes) {
198
-            $classnames = array_keys($this->_payment_method_types);
199
-            $payment_methods = array();
200
-            foreach ($classnames as $classname) {
201
-                $payment_methods[] = $this->payment_method_class_from_type($classname);
202
-            }
203
-            return $payment_methods;
204
-        }
205
-        return array_keys($this->_payment_method_types);
206
-    }
207
-
208
-
209
-
210
-    /**
211
-     * Gets an object of each payment method type, none of which are bound to a
212
-     * payment method instance
213
-     *
214
-     * @param boolean $force_recheck whether to force re-checking for new payment method types
215
-     * @return EE_PMT_Base[]
216
-     */
217
-    public function payment_method_types($force_recheck = false)
218
-    {
219
-        $this->maybe_register_payment_methods($force_recheck);
220
-        $payment_method_objects = array();
221
-        foreach ($this->payment_method_type_names(true) as $classname) {
222
-            $payment_method_objects[] = new $classname;
223
-        }
224
-        return $payment_method_objects;
225
-    }
226
-
227
-
228
-
229
-    /**
230
-     * Changes the payment method's classname into the payment method type's name
231
-     * (as used on the payment method's table's PMD_type field)
232
-     *
233
-     * @param string $classname
234
-     * @return string
235
-     */
236
-    public function payment_method_type_sans_class_prefix($classname)
237
-    {
238
-        return str_replace('EE_PMT_', '', $classname);
239
-    }
240
-
241
-
242
-
243
-    /**
244
-     * Does the opposite of payment-method_type_sans_prefix
245
-     *
246
-     * @param string $type
247
-     * @return string
248
-     */
249
-    public function payment_method_class_from_type($type)
250
-    {
251
-        $this->maybe_register_payment_methods();
252
-        return 'EE_PMT_' . $type;
253
-    }
254
-
255
-
256
-
257
-    /**
258
-     * Activates a payment method of the given type.
259
-     *
260
-     * @param string $payment_method_type the PMT_type; for EE_PMT_Invoice this would be 'Invoice'
261
-     * @return EE_Payment_Method
262
-     * @throws EE_Error
263
-     */
264
-    public function activate_a_payment_method_of_type($payment_method_type)
265
-    {
266
-        $payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
267
-        if (! $payment_method instanceof EE_Payment_Method) {
268
-            $pm_type_class = $this->payment_method_class_from_type($payment_method_type);
269
-            if (class_exists($pm_type_class)) {
270
-                /** @var $pm_type_obj EE_PMT_Base */
271
-                $pm_type_obj = new $pm_type_class;
272
-                $payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
273
-                if (! $payment_method) {
274
-                    $payment_method = $this->create_payment_method_of_type($pm_type_obj);
275
-                }
276
-                $payment_method->set_type($payment_method_type);
277
-                $this->initialize_payment_method($payment_method);
278
-            } else {
279
-                throw new EE_Error(
280
-                    sprintf(
281
-                        esc_html__(
282
-                            'There is no payment method of type %1$s, so it could not be activated',
283
-                            'event_espresso'
284
-                        ),
285
-                        $pm_type_class
286
-                    )
287
-                );
288
-            }
289
-        }
290
-        $payment_method->set_active();
291
-        $payment_method->save();
292
-        if ($payment_method->type() === 'Invoice') {
293
-            /** @type EE_Message_Resource_Manager $message_resource_manager */
294
-            $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
295
-            $message_resource_manager->ensure_message_type_is_active('invoice', 'html');
296
-            $message_resource_manager->ensure_messenger_is_active('pdf');
297
-            EE_Error::add_persistent_admin_notice(
298
-                'invoice_pm_requirements_notice',
299
-                sprintf(
300
-                    esc_html__(
301
-                        'The Invoice payment method has been activated. It requires the invoice message type, html messenger, and pdf messenger be activated as well for the %1$smessages system%2$s, so it has been automatically verified that they are also active.',
302
-                        'event_espresso'
303
-                    ),
304
-                    '<a href="' . admin_url('admin.php?page=espresso_messages') . '">',
305
-                    '</a>'
306
-                ),
307
-                true
308
-            );
309
-        }
310
-        return $payment_method;
311
-    }
312
-
313
-
314
-
315
-    /**
316
-     * Creates a payment method of the specified type. Does not save it.
317
-     *
318
-     * @global WP_User    $current_user
319
-     * @param EE_PMT_Base $pm_type_obj
320
-     * @return EE_Payment_Method
321
-     * @throws EE_Error
322
-     */
323
-    public function create_payment_method_of_type($pm_type_obj)
324
-    {
325
-        global $current_user;
326
-        $payment_method = EE_Payment_Method::new_instance(
327
-            array(
328
-                'PMD_type'       => $pm_type_obj->system_name(),
329
-                'PMD_name'       => $pm_type_obj->pretty_name(),
330
-                'PMD_admin_name' => $pm_type_obj->pretty_name(),
331
-                'PMD_slug'       => $pm_type_obj->system_name(),//automatically converted to slug
332
-                'PMD_wp_user'    => $current_user->ID,
333
-                'PMD_order'      => EEM_Payment_Method::instance()->count(
334
-                        array(array('PMD_type' => array('!=', 'Admin_Only')))
335
-                    ) * 10,
336
-            )
337
-        );
338
-        return $payment_method;
339
-    }
340
-
341
-
342
-
343
-    /**
344
-     * Sets the initial payment method properties (including extra meta)
345
-     *
346
-     * @param EE_Payment_Method $payment_method
347
-     * @return EE_Payment_Method
348
-     * @throws EE_Error
349
-     */
350
-    public function initialize_payment_method($payment_method)
351
-    {
352
-        $pm_type_obj = $payment_method->type_obj();
353
-        $payment_method->set_description($pm_type_obj->default_description());
354
-        if (! $payment_method->button_url()) {
355
-            $payment_method->set_button_url($pm_type_obj->default_button_url());
356
-        }
357
-        //now add setup its default extra meta properties
358
-        $extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs();
359
-        if (! empty($extra_metas)) {
360
-            //verify the payment method has an ID before adding extra meta
361
-            if (! $payment_method->ID()) {
362
-                $payment_method->save();
363
-            }
364
-            foreach ($extra_metas as $meta_name => $input) {
365
-                $payment_method->update_extra_meta($meta_name, $input->raw_value());
366
-            }
367
-        }
368
-        return $payment_method;
369
-    }
370
-
371
-
372
-
373
-    /**
374
-     * Makes sure the payment method is related to the specified payment method
375
-     *
376
-     * @deprecated in 4.9.40 because the currency payment method table is being deprecated
377
-     * @param EE_Payment_Method $payment_method
378
-     * @return EE_Payment_Method
379
-     * @throws EE_Error
380
-     */
381
-    public function set_usable_currencies_on_payment_method($payment_method)
382
-    {
383
-        EE_Error::doing_it_wrong(
384
-            'EE_Payment_Method_Manager::set_usable_currencies_on_payment_method',
385
-            esc_html__(
386
-                'We no longer define what currencies are usable by payment methods. Its not used nor efficient.',
387
-                'event_espresso'
388
-            ),
389
-            '4.9.40'
390
-        );
391
-        return $payment_method;
392
-    }
393
-
394
-
395
-
396
-    /**
397
-     * Deactivates a payment method of the given payment method slug.
398
-     *
399
-     * @param string $payment_method_slug The slug for the payment method to deactivate.
400
-     * @return int count of rows updated.
401
-     * @throws EE_Error
402
-     */
403
-    public function deactivate_payment_method($payment_method_slug)
404
-    {
405
-        EE_Log::instance()->log(
406
-            __FILE__,
407
-            __FUNCTION__,
408
-            sprintf(
409
-                esc_html__(
410
-                    'Payment method with slug %1$s is being deactivated by site admin',
411
-                    'event_espresso'
412
-                ),
413
-                $payment_method_slug
414
-            ),
415
-            'payment_method_change'
416
-        );
417
-        $count_updated = EEM_Payment_Method::instance()->update(
418
-            array('PMD_scope' => array()),
419
-            array(array('PMD_slug' => $payment_method_slug))
420
-        );
421
-        return $count_updated;
422
-    }
423
-
424
-
425
-
426
-    /**
427
-     * callback for FHEE__EE_Capabilities__init_caps_map__caps filter to add dynamic payment method
428
-     * access caps.
429
-     *
430
-     * @param array $caps capabilities being filtered
431
-     * @return array
432
-     */
433
-    public function add_payment_method_caps($caps)
434
-    {
435
-        /* add dynamic caps from payment methods
22
+	/**
23
+	 * @var EE_Payment_Method_Manager $_instance
24
+	 */
25
+	private static $_instance;
26
+
27
+	/**
28
+	 * @var array keys are class names without 'EE_PMT_', values are their filepaths
29
+	 */
30
+	protected $_payment_method_types = array();
31
+
32
+
33
+
34
+	/**
35
+	 * @singleton method used to instantiate class object
36
+	 * @return EE_Payment_Method_Manager instance
37
+	 */
38
+	public static function instance()
39
+	{
40
+		// check if class object is instantiated, and instantiated properly
41
+		if (! self::$_instance instanceof EE_Payment_Method_Manager) {
42
+			self::$_instance = new self();
43
+		}
44
+		EE_Registry::instance()->load_lib('PMT_Base');
45
+		return self::$_instance;
46
+	}
47
+
48
+
49
+
50
+	/**
51
+	 * Resets the instance and returns a new one
52
+	 *
53
+	 * @return EE_Payment_Method_Manager
54
+	 */
55
+	public static function reset()
56
+	{
57
+		self::$_instance = null;
58
+		return self::instance();
59
+	}
60
+
61
+
62
+
63
+	/**
64
+	 * If necessary, re-register payment methods
65
+	 *
66
+	 * @param boolean $force_recheck whether to recheck for payment method types,
67
+	 *                               or just re-use the PMTs we found last time we checked during this request (if
68
+	 *                               we have not yet checked during this request, then we need to check anyways)
69
+	 */
70
+	public function maybe_register_payment_methods($force_recheck = false)
71
+	{
72
+		if (! $this->_payment_method_types || $force_recheck) {
73
+			$this->_register_payment_methods();
74
+			//if in admin lets ensure caps are set.
75
+			if (is_admin()) {
76
+				add_filter('FHEE__EE_Capabilities__init_caps_map__caps', array($this, 'add_payment_method_caps'));
77
+				EE_Registry::instance()->CAP->init_caps();
78
+			}
79
+		}
80
+	}
81
+
82
+
83
+
84
+	/**
85
+	 * register_payment_methods
86
+	 *
87
+	 * @return array
88
+	 */
89
+	protected function _register_payment_methods()
90
+	{
91
+		// grab list of installed modules
92
+		$pm_to_register = glob(EE_PAYMENT_METHODS . '*', GLOB_ONLYDIR);
93
+		// filter list of modules to register
94
+		$pm_to_register = apply_filters(
95
+			'FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register',
96
+			$pm_to_register
97
+		);
98
+		// loop through folders
99
+		foreach ($pm_to_register as $pm_path) {
100
+			$this->register_payment_method($pm_path);
101
+		}
102
+		do_action('FHEE__EE_Payment_Method_Manager__register_payment_methods__registered_payment_methods');
103
+		// filter list of installed modules
104
+		//keep them organized alphabetically by the payment method type's name
105
+		ksort($this->_payment_method_types);
106
+		return apply_filters(
107
+			'FHEE__EE_Payment_Method_Manager__register_payment_methods__installed_payment_methods',
108
+			$this->_payment_method_types
109
+		);
110
+	}
111
+
112
+
113
+
114
+	/**
115
+	 * register_payment_method- makes core aware of this payment method
116
+	 *
117
+	 * @param string $payment_method_path - full path up to and including payment method folder
118
+	 * @return boolean
119
+	 */
120
+	public function register_payment_method($payment_method_path = '')
121
+	{
122
+		do_action('AHEE__EE_Payment_Method_Manager__register_payment_method__begin', $payment_method_path);
123
+		$module_ext = '.pm.php';
124
+		// make all separators match
125
+		$payment_method_path = rtrim(str_replace('/\\', DS, $payment_method_path), DS);
126
+		// grab and sanitize module name
127
+		$module_dir = basename($payment_method_path);
128
+		// create classname from module directory name
129
+		$module = str_replace(array('_', ' '), array(' ', '_'), $module_dir);
130
+		// add class prefix
131
+		$module_class = 'EE_PMT_' . $module;
132
+		// does the module exist ?
133
+		if (! is_readable($payment_method_path . DS . $module_class . $module_ext)) {
134
+			$msg = sprintf(
135
+				esc_html__(
136
+					'The requested %s payment method file could not be found or is not readable due to file permissions.',
137
+					'event_espresso'
138
+				), $module
139
+			);
140
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
141
+			return false;
142
+		}
143
+		// load the module class file
144
+		require_once($payment_method_path . DS . $module_class . $module_ext);
145
+		// verify that class exists
146
+		if (! class_exists($module_class)) {
147
+			$msg = sprintf(
148
+				esc_html__('The requested %s module class does not exist.', 'event_espresso'),
149
+				$module_class
150
+			);
151
+			EE_Error::add_error($msg . '||' . $msg, __FILE__, __FUNCTION__, __LINE__);
152
+			return false;
153
+		}
154
+		// add to array of registered modules
155
+		$this->_payment_method_types[$module] = $payment_method_path . DS . $module_class . $module_ext;
156
+		return true;
157
+	}
158
+
159
+
160
+
161
+	/**
162
+	 * Checks if a payment method has been registered, and if so includes it
163
+	 *
164
+	 * @param string  $payment_method_name like 'PayPal_Pro', (ie classname without the prefix 'EEPM_')
165
+	 * @param boolean $force_recheck       whether to force re-checking for new payment method types
166
+	 * @return boolean
167
+	 */
168
+	public function payment_method_type_exists($payment_method_name, $force_recheck = false)
169
+	{
170
+		if (
171
+			$force_recheck
172
+			|| ! is_array($this->_payment_method_types)
173
+			|| ! isset($this->_payment_method_types[$payment_method_name])
174
+		) {
175
+			$this->maybe_register_payment_methods($force_recheck);
176
+		}
177
+		if (isset($this->_payment_method_types[$payment_method_name])) {
178
+			require_once($this->_payment_method_types[$payment_method_name]);
179
+			return true;
180
+		}
181
+		return false;
182
+	}
183
+
184
+
185
+
186
+	/**
187
+	 * Returns all the class names of the various payment method types
188
+	 *
189
+	 * @param boolean $with_prefixes TRUE: get payment method type class names; false just their 'names'
190
+	 *                               (what you'd find in wp_esp_payment_method.PMD_type)
191
+	 * @param boolean $force_recheck whether to force re-checking for new payment method types
192
+	 * @return array
193
+	 */
194
+	public function payment_method_type_names($with_prefixes = false, $force_recheck = false)
195
+	{
196
+		$this->maybe_register_payment_methods($force_recheck);
197
+		if ($with_prefixes) {
198
+			$classnames = array_keys($this->_payment_method_types);
199
+			$payment_methods = array();
200
+			foreach ($classnames as $classname) {
201
+				$payment_methods[] = $this->payment_method_class_from_type($classname);
202
+			}
203
+			return $payment_methods;
204
+		}
205
+		return array_keys($this->_payment_method_types);
206
+	}
207
+
208
+
209
+
210
+	/**
211
+	 * Gets an object of each payment method type, none of which are bound to a
212
+	 * payment method instance
213
+	 *
214
+	 * @param boolean $force_recheck whether to force re-checking for new payment method types
215
+	 * @return EE_PMT_Base[]
216
+	 */
217
+	public function payment_method_types($force_recheck = false)
218
+	{
219
+		$this->maybe_register_payment_methods($force_recheck);
220
+		$payment_method_objects = array();
221
+		foreach ($this->payment_method_type_names(true) as $classname) {
222
+			$payment_method_objects[] = new $classname;
223
+		}
224
+		return $payment_method_objects;
225
+	}
226
+
227
+
228
+
229
+	/**
230
+	 * Changes the payment method's classname into the payment method type's name
231
+	 * (as used on the payment method's table's PMD_type field)
232
+	 *
233
+	 * @param string $classname
234
+	 * @return string
235
+	 */
236
+	public function payment_method_type_sans_class_prefix($classname)
237
+	{
238
+		return str_replace('EE_PMT_', '', $classname);
239
+	}
240
+
241
+
242
+
243
+	/**
244
+	 * Does the opposite of payment-method_type_sans_prefix
245
+	 *
246
+	 * @param string $type
247
+	 * @return string
248
+	 */
249
+	public function payment_method_class_from_type($type)
250
+	{
251
+		$this->maybe_register_payment_methods();
252
+		return 'EE_PMT_' . $type;
253
+	}
254
+
255
+
256
+
257
+	/**
258
+	 * Activates a payment method of the given type.
259
+	 *
260
+	 * @param string $payment_method_type the PMT_type; for EE_PMT_Invoice this would be 'Invoice'
261
+	 * @return EE_Payment_Method
262
+	 * @throws EE_Error
263
+	 */
264
+	public function activate_a_payment_method_of_type($payment_method_type)
265
+	{
266
+		$payment_method = EEM_Payment_Method::instance()->get_one_of_type($payment_method_type);
267
+		if (! $payment_method instanceof EE_Payment_Method) {
268
+			$pm_type_class = $this->payment_method_class_from_type($payment_method_type);
269
+			if (class_exists($pm_type_class)) {
270
+				/** @var $pm_type_obj EE_PMT_Base */
271
+				$pm_type_obj = new $pm_type_class;
272
+				$payment_method = EEM_Payment_Method::instance()->get_one_by_slug($pm_type_obj->system_name());
273
+				if (! $payment_method) {
274
+					$payment_method = $this->create_payment_method_of_type($pm_type_obj);
275
+				}
276
+				$payment_method->set_type($payment_method_type);
277
+				$this->initialize_payment_method($payment_method);
278
+			} else {
279
+				throw new EE_Error(
280
+					sprintf(
281
+						esc_html__(
282
+							'There is no payment method of type %1$s, so it could not be activated',
283
+							'event_espresso'
284
+						),
285
+						$pm_type_class
286
+					)
287
+				);
288
+			}
289
+		}
290
+		$payment_method->set_active();
291
+		$payment_method->save();
292
+		if ($payment_method->type() === 'Invoice') {
293
+			/** @type EE_Message_Resource_Manager $message_resource_manager */
294
+			$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
295
+			$message_resource_manager->ensure_message_type_is_active('invoice', 'html');
296
+			$message_resource_manager->ensure_messenger_is_active('pdf');
297
+			EE_Error::add_persistent_admin_notice(
298
+				'invoice_pm_requirements_notice',
299
+				sprintf(
300
+					esc_html__(
301
+						'The Invoice payment method has been activated. It requires the invoice message type, html messenger, and pdf messenger be activated as well for the %1$smessages system%2$s, so it has been automatically verified that they are also active.',
302
+						'event_espresso'
303
+					),
304
+					'<a href="' . admin_url('admin.php?page=espresso_messages') . '">',
305
+					'</a>'
306
+				),
307
+				true
308
+			);
309
+		}
310
+		return $payment_method;
311
+	}
312
+
313
+
314
+
315
+	/**
316
+	 * Creates a payment method of the specified type. Does not save it.
317
+	 *
318
+	 * @global WP_User    $current_user
319
+	 * @param EE_PMT_Base $pm_type_obj
320
+	 * @return EE_Payment_Method
321
+	 * @throws EE_Error
322
+	 */
323
+	public function create_payment_method_of_type($pm_type_obj)
324
+	{
325
+		global $current_user;
326
+		$payment_method = EE_Payment_Method::new_instance(
327
+			array(
328
+				'PMD_type'       => $pm_type_obj->system_name(),
329
+				'PMD_name'       => $pm_type_obj->pretty_name(),
330
+				'PMD_admin_name' => $pm_type_obj->pretty_name(),
331
+				'PMD_slug'       => $pm_type_obj->system_name(),//automatically converted to slug
332
+				'PMD_wp_user'    => $current_user->ID,
333
+				'PMD_order'      => EEM_Payment_Method::instance()->count(
334
+						array(array('PMD_type' => array('!=', 'Admin_Only')))
335
+					) * 10,
336
+			)
337
+		);
338
+		return $payment_method;
339
+	}
340
+
341
+
342
+
343
+	/**
344
+	 * Sets the initial payment method properties (including extra meta)
345
+	 *
346
+	 * @param EE_Payment_Method $payment_method
347
+	 * @return EE_Payment_Method
348
+	 * @throws EE_Error
349
+	 */
350
+	public function initialize_payment_method($payment_method)
351
+	{
352
+		$pm_type_obj = $payment_method->type_obj();
353
+		$payment_method->set_description($pm_type_obj->default_description());
354
+		if (! $payment_method->button_url()) {
355
+			$payment_method->set_button_url($pm_type_obj->default_button_url());
356
+		}
357
+		//now add setup its default extra meta properties
358
+		$extra_metas = $pm_type_obj->settings_form()->extra_meta_inputs();
359
+		if (! empty($extra_metas)) {
360
+			//verify the payment method has an ID before adding extra meta
361
+			if (! $payment_method->ID()) {
362
+				$payment_method->save();
363
+			}
364
+			foreach ($extra_metas as $meta_name => $input) {
365
+				$payment_method->update_extra_meta($meta_name, $input->raw_value());
366
+			}
367
+		}
368
+		return $payment_method;
369
+	}
370
+
371
+
372
+
373
+	/**
374
+	 * Makes sure the payment method is related to the specified payment method
375
+	 *
376
+	 * @deprecated in 4.9.40 because the currency payment method table is being deprecated
377
+	 * @param EE_Payment_Method $payment_method
378
+	 * @return EE_Payment_Method
379
+	 * @throws EE_Error
380
+	 */
381
+	public function set_usable_currencies_on_payment_method($payment_method)
382
+	{
383
+		EE_Error::doing_it_wrong(
384
+			'EE_Payment_Method_Manager::set_usable_currencies_on_payment_method',
385
+			esc_html__(
386
+				'We no longer define what currencies are usable by payment methods. Its not used nor efficient.',
387
+				'event_espresso'
388
+			),
389
+			'4.9.40'
390
+		);
391
+		return $payment_method;
392
+	}
393
+
394
+
395
+
396
+	/**
397
+	 * Deactivates a payment method of the given payment method slug.
398
+	 *
399
+	 * @param string $payment_method_slug The slug for the payment method to deactivate.
400
+	 * @return int count of rows updated.
401
+	 * @throws EE_Error
402
+	 */
403
+	public function deactivate_payment_method($payment_method_slug)
404
+	{
405
+		EE_Log::instance()->log(
406
+			__FILE__,
407
+			__FUNCTION__,
408
+			sprintf(
409
+				esc_html__(
410
+					'Payment method with slug %1$s is being deactivated by site admin',
411
+					'event_espresso'
412
+				),
413
+				$payment_method_slug
414
+			),
415
+			'payment_method_change'
416
+		);
417
+		$count_updated = EEM_Payment_Method::instance()->update(
418
+			array('PMD_scope' => array()),
419
+			array(array('PMD_slug' => $payment_method_slug))
420
+		);
421
+		return $count_updated;
422
+	}
423
+
424
+
425
+
426
+	/**
427
+	 * callback for FHEE__EE_Capabilities__init_caps_map__caps filter to add dynamic payment method
428
+	 * access caps.
429
+	 *
430
+	 * @param array $caps capabilities being filtered
431
+	 * @return array
432
+	 */
433
+	public function add_payment_method_caps($caps)
434
+	{
435
+		/* add dynamic caps from payment methods
436 436
          * at the time of writing, october 20 2014, these are the caps added:
437 437
          * ee_payment_method_admin_only
438 438
          * ee_payment_method_aim
@@ -446,10 +446,10 @@  discard block
 block discarded – undo
446 446
          * their related capability automatically added too, so long as they are
447 447
          * registered properly using EE_Register_Payment_Method::register()
448 448
          */
449
-        foreach ($this->payment_method_types() as $payment_method_type_obj) {
450
-            $caps['administrator'][] = $payment_method_type_obj->cap_name();
451
-        }
452
-        return $caps;
453
-    }
449
+		foreach ($this->payment_method_types() as $payment_method_type_obj) {
450
+			$caps['administrator'][] = $payment_method_type_obj->cap_name();
451
+		}
452
+		return $caps;
453
+	}
454 454
 
455 455
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Activation.helper.php 1 patch
Indentation   +1653 added lines, -1653 removed lines patch added patch discarded remove patch
@@ -2,7 +2,7 @@  discard block
 block discarded – undo
2 2
 use EventEspresso\core\interfaces\ResettableInterface;
3 3
 
4 4
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
5
-    exit('No direct script access allowed');
5
+	exit('No direct script access allowed');
6 6
 }
7 7
 
8 8
 
@@ -17,244 +17,244 @@  discard block
 block discarded – undo
17 17
 class EEH_Activation implements ResettableInterface
18 18
 {
19 19
 
20
-    /**
21
-     * constant used to indicate a cron task is no longer in use
22
-     */
23
-    const cron_task_no_longer_in_use = 'no_longer_in_use';
24
-
25
-    /**
26
-     * option name that will indicate whether or not we still
27
-     * need to create EE's folders in the uploads directory
28
-     * (because if EE was installed without file system access,
29
-     * we need to request credentials before we can create them)
30
-     */
31
-    const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
32
-
33
-    /**
34
-     * WP_User->ID
35
-     *
36
-     * @var int
37
-     */
38
-    private static $_default_creator_id;
39
-
40
-    /**
41
-     * indicates whether or not we've already verified core's default data during this request,
42
-     * because after migrations are done, any addons activated while in maintenance mode
43
-     * will want to setup their own default data, and they might hook into core's default data
44
-     * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
45
-     * This prevents doing that for EVERY single addon.
46
-     *
47
-     * @var boolean
48
-     */
49
-    protected static $_initialized_db_content_already_in_this_request = false;
50
-
51
-    /**
52
-     * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
53
-     */
54
-    private static $table_analysis;
55
-
56
-    /**
57
-     * @var \EventEspresso\core\services\database\TableManager $table_manager
58
-     */
59
-    private static $table_manager;
60
-
61
-
62
-    /**
63
-     * @return \EventEspresso\core\services\database\TableAnalysis
64
-     */
65
-    public static function getTableAnalysis()
66
-    {
67
-        if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
68
-            self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
69
-        }
70
-        return self::$table_analysis;
71
-    }
72
-
73
-
74
-    /**
75
-     * @return \EventEspresso\core\services\database\TableManager
76
-     */
77
-    public static function getTableManager()
78
-    {
79
-        if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
80
-            self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
81
-        }
82
-        return self::$table_manager;
83
-    }
84
-
85
-
86
-    /**
87
-     *    _ensure_table_name_has_prefix
88
-     *
89
-     * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
90
-     * @access     public
91
-     * @static
92
-     * @param $table_name
93
-     * @return string
94
-     */
95
-    public static function ensure_table_name_has_prefix($table_name)
96
-    {
97
-        return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
98
-    }
99
-
100
-
101
-    /**
102
-     *    system_initialization
103
-     *    ensures the EE configuration settings are loaded with at least default options set
104
-     *    and that all critical EE pages have been generated with the appropriate shortcodes in place
105
-     *
106
-     * @access public
107
-     * @static
108
-     * @return void
109
-     */
110
-    public static function system_initialization()
111
-    {
112
-        EEH_Activation::reset_and_update_config();
113
-        //which is fired BEFORE activation of plugin anyways
114
-        EEH_Activation::verify_default_pages_exist();
115
-    }
116
-
117
-
118
-    /**
119
-     * Sets the database schema and creates folders. This should
120
-     * be called on plugin activation and reactivation
121
-     *
122
-     * @return boolean success, whether the database and folders are setup properly
123
-     * @throws \EE_Error
124
-     */
125
-    public static function initialize_db_and_folders()
126
-    {
127
-        $good_filesystem = EEH_Activation::create_upload_directories();
128
-        $good_db         = EEH_Activation::create_database_tables();
129
-        return $good_filesystem && $good_db;
130
-    }
131
-
132
-
133
-    /**
134
-     * assuming we have an up-to-date database schema, this will populate it
135
-     * with default and initial data. This should be called
136
-     * upon activation of a new plugin, reactivation, and at the end
137
-     * of running migration scripts
138
-     *
139
-     * @throws \EE_Error
140
-     */
141
-    public static function initialize_db_content()
142
-    {
143
-        //let's avoid doing all this logic repeatedly, especially when addons are requesting it
144
-        if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
145
-            return;
146
-        }
147
-        EEH_Activation::$_initialized_db_content_already_in_this_request = true;
148
-
149
-        EEH_Activation::initialize_system_questions();
150
-        EEH_Activation::insert_default_status_codes();
151
-        EEH_Activation::generate_default_message_templates();
152
-        EEH_Activation::create_no_ticket_prices_array();
153
-        EE_Registry::instance()->CAP->init_caps();
154
-
155
-        EEH_Activation::validate_messages_system();
156
-        EEH_Activation::insert_default_payment_methods();
157
-        //in case we've
158
-        EEH_Activation::remove_cron_tasks();
159
-        EEH_Activation::create_cron_tasks();
160
-        // remove all TXN locks since that is being done via extra meta now
161
-        delete_option('ee_locked_transactions');
162
-        //also, check for CAF default db content
163
-        do_action('AHEE__EEH_Activation__initialize_db_content');
164
-        //also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
165
-        //which users really won't care about on initial activation
166
-        EE_Error::overwrite_success();
167
-    }
168
-
169
-
170
-    /**
171
-     * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
172
-     * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
173
-     * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
174
-     * (null)
175
-     *
176
-     * @param string $which_to_include can be 'current' (ones that are currently in use),
177
-     *                                 'old' (only returns ones that should no longer be used),or 'all',
178
-     * @return array
179
-     * @throws \EE_Error
180
-     */
181
-    public static function get_cron_tasks($which_to_include)
182
-    {
183
-        $cron_tasks = apply_filters(
184
-            'FHEE__EEH_Activation__get_cron_tasks',
185
-            array(
186
-                'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
20
+	/**
21
+	 * constant used to indicate a cron task is no longer in use
22
+	 */
23
+	const cron_task_no_longer_in_use = 'no_longer_in_use';
24
+
25
+	/**
26
+	 * option name that will indicate whether or not we still
27
+	 * need to create EE's folders in the uploads directory
28
+	 * (because if EE was installed without file system access,
29
+	 * we need to request credentials before we can create them)
30
+	 */
31
+	const upload_directories_incomplete_option_name = 'ee_upload_directories_incomplete';
32
+
33
+	/**
34
+	 * WP_User->ID
35
+	 *
36
+	 * @var int
37
+	 */
38
+	private static $_default_creator_id;
39
+
40
+	/**
41
+	 * indicates whether or not we've already verified core's default data during this request,
42
+	 * because after migrations are done, any addons activated while in maintenance mode
43
+	 * will want to setup their own default data, and they might hook into core's default data
44
+	 * and trigger core to setup its default data. In which case they might all ask for core to init its default data.
45
+	 * This prevents doing that for EVERY single addon.
46
+	 *
47
+	 * @var boolean
48
+	 */
49
+	protected static $_initialized_db_content_already_in_this_request = false;
50
+
51
+	/**
52
+	 * @var \EventEspresso\core\services\database\TableAnalysis $table_analysis
53
+	 */
54
+	private static $table_analysis;
55
+
56
+	/**
57
+	 * @var \EventEspresso\core\services\database\TableManager $table_manager
58
+	 */
59
+	private static $table_manager;
60
+
61
+
62
+	/**
63
+	 * @return \EventEspresso\core\services\database\TableAnalysis
64
+	 */
65
+	public static function getTableAnalysis()
66
+	{
67
+		if (! self::$table_analysis instanceof \EventEspresso\core\services\database\TableAnalysis) {
68
+			self::$table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true);
69
+		}
70
+		return self::$table_analysis;
71
+	}
72
+
73
+
74
+	/**
75
+	 * @return \EventEspresso\core\services\database\TableManager
76
+	 */
77
+	public static function getTableManager()
78
+	{
79
+		if (! self::$table_manager instanceof \EventEspresso\core\services\database\TableManager) {
80
+			self::$table_manager = EE_Registry::instance()->create('TableManager', array(), true);
81
+		}
82
+		return self::$table_manager;
83
+	}
84
+
85
+
86
+	/**
87
+	 *    _ensure_table_name_has_prefix
88
+	 *
89
+	 * @deprecated instead use TableAnalysis::ensureTableNameHasPrefix()
90
+	 * @access     public
91
+	 * @static
92
+	 * @param $table_name
93
+	 * @return string
94
+	 */
95
+	public static function ensure_table_name_has_prefix($table_name)
96
+	{
97
+		return \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix($table_name);
98
+	}
99
+
100
+
101
+	/**
102
+	 *    system_initialization
103
+	 *    ensures the EE configuration settings are loaded with at least default options set
104
+	 *    and that all critical EE pages have been generated with the appropriate shortcodes in place
105
+	 *
106
+	 * @access public
107
+	 * @static
108
+	 * @return void
109
+	 */
110
+	public static function system_initialization()
111
+	{
112
+		EEH_Activation::reset_and_update_config();
113
+		//which is fired BEFORE activation of plugin anyways
114
+		EEH_Activation::verify_default_pages_exist();
115
+	}
116
+
117
+
118
+	/**
119
+	 * Sets the database schema and creates folders. This should
120
+	 * be called on plugin activation and reactivation
121
+	 *
122
+	 * @return boolean success, whether the database and folders are setup properly
123
+	 * @throws \EE_Error
124
+	 */
125
+	public static function initialize_db_and_folders()
126
+	{
127
+		$good_filesystem = EEH_Activation::create_upload_directories();
128
+		$good_db         = EEH_Activation::create_database_tables();
129
+		return $good_filesystem && $good_db;
130
+	}
131
+
132
+
133
+	/**
134
+	 * assuming we have an up-to-date database schema, this will populate it
135
+	 * with default and initial data. This should be called
136
+	 * upon activation of a new plugin, reactivation, and at the end
137
+	 * of running migration scripts
138
+	 *
139
+	 * @throws \EE_Error
140
+	 */
141
+	public static function initialize_db_content()
142
+	{
143
+		//let's avoid doing all this logic repeatedly, especially when addons are requesting it
144
+		if (EEH_Activation::$_initialized_db_content_already_in_this_request) {
145
+			return;
146
+		}
147
+		EEH_Activation::$_initialized_db_content_already_in_this_request = true;
148
+
149
+		EEH_Activation::initialize_system_questions();
150
+		EEH_Activation::insert_default_status_codes();
151
+		EEH_Activation::generate_default_message_templates();
152
+		EEH_Activation::create_no_ticket_prices_array();
153
+		EE_Registry::instance()->CAP->init_caps();
154
+
155
+		EEH_Activation::validate_messages_system();
156
+		EEH_Activation::insert_default_payment_methods();
157
+		//in case we've
158
+		EEH_Activation::remove_cron_tasks();
159
+		EEH_Activation::create_cron_tasks();
160
+		// remove all TXN locks since that is being done via extra meta now
161
+		delete_option('ee_locked_transactions');
162
+		//also, check for CAF default db content
163
+		do_action('AHEE__EEH_Activation__initialize_db_content');
164
+		//also: EEM_Gateways::load_all_gateways() outputs a lot of success messages
165
+		//which users really won't care about on initial activation
166
+		EE_Error::overwrite_success();
167
+	}
168
+
169
+
170
+	/**
171
+	 * Returns an array of cron tasks. Array values are the actions fired by the cron tasks (the "hooks"),
172
+	 * values are the frequency (the "recurrence"). See http://codex.wordpress.org/Function_Reference/wp_schedule_event
173
+	 * If the cron task should NO longer be used, it should have a value of EEH_Activation::cron_task_no_longer_in_use
174
+	 * (null)
175
+	 *
176
+	 * @param string $which_to_include can be 'current' (ones that are currently in use),
177
+	 *                                 'old' (only returns ones that should no longer be used),or 'all',
178
+	 * @return array
179
+	 * @throws \EE_Error
180
+	 */
181
+	public static function get_cron_tasks($which_to_include)
182
+	{
183
+		$cron_tasks = apply_filters(
184
+			'FHEE__EEH_Activation__get_cron_tasks',
185
+			array(
186
+				'AHEE__EE_Cron_Tasks__clean_up_junk_transactions'      => 'hourly',
187 187
 //				'AHEE__EE_Cron_Tasks__finalize_abandoned_transactions' => EEH_Activation::cron_task_no_longer_in_use, actually this is still in use
188
-                'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
189
-                //there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
190
-                'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
191
-            )
192
-        );
193
-        if ($which_to_include === 'old') {
194
-            $cron_tasks = array_filter(
195
-                $cron_tasks,
196
-                function ($value) {
197
-                    return $value === EEH_Activation::cron_task_no_longer_in_use;
198
-                }
199
-            );
200
-        } elseif ($which_to_include === 'current') {
201
-            $cron_tasks = array_filter($cron_tasks);
202
-        } elseif (WP_DEBUG && $which_to_include !== 'all') {
203
-            throw new EE_Error(
204
-                sprintf(
205
-                    __(
206
-                        'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
207
-                        'event_espresso'
208
-                    ),
209
-                    $which_to_include
210
-                )
211
-            );
212
-        }
213
-        return $cron_tasks;
214
-    }
215
-
216
-
217
-    /**
218
-     * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
219
-     *
220
-     * @throws \EE_Error
221
-     */
222
-    public static function create_cron_tasks()
223
-    {
224
-
225
-        foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
226
-            if (! wp_next_scheduled($hook_name)) {
227
-                /**
228
-                 * This allows client code to define the initial start timestamp for this schedule.
229
-                 */
230
-                if (is_array($frequency)
231
-                    && count($frequency) === 2
232
-                    && isset($frequency[0], $frequency[1])
233
-                ) {
234
-                    $start_timestamp = $frequency[0];
235
-                    $frequency = $frequency[1];
236
-                } else {
237
-                    $start_timestamp = time();
238
-                }
239
-                wp_schedule_event($start_timestamp, $frequency, $hook_name);
240
-            }
241
-        }
242
-
243
-    }
244
-
245
-
246
-    /**
247
-     * Remove the currently-existing and now-removed cron tasks.
248
-     *
249
-     * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
250
-     * @throws \EE_Error
251
-     */
252
-    public static function remove_cron_tasks($remove_all = true)
253
-    {
254
-        $cron_tasks_to_remove = $remove_all ? 'all' : 'old';
255
-        $crons                = _get_cron_array();
256
-        $crons                = is_array($crons) ? $crons : array();
257
-        /* reminder of what $crons look like:
188
+				'AHEE__EE_Cron_Tasks__update_transaction_with_payment' => EEH_Activation::cron_task_no_longer_in_use,
189
+				//there may have been a bug which prevented from these cron tasks from getting unscheduled, so we might want to remove these for a few updates
190
+				'AHEE_EE_Cron_Tasks__clean_out_old_gateway_logs'       => 'daily',
191
+			)
192
+		);
193
+		if ($which_to_include === 'old') {
194
+			$cron_tasks = array_filter(
195
+				$cron_tasks,
196
+				function ($value) {
197
+					return $value === EEH_Activation::cron_task_no_longer_in_use;
198
+				}
199
+			);
200
+		} elseif ($which_to_include === 'current') {
201
+			$cron_tasks = array_filter($cron_tasks);
202
+		} elseif (WP_DEBUG && $which_to_include !== 'all') {
203
+			throw new EE_Error(
204
+				sprintf(
205
+					__(
206
+						'Invalid argument of "%1$s" passed to EEH_Activation::get_cron_tasks. Valid values are "all", "old" and "current".',
207
+						'event_espresso'
208
+					),
209
+					$which_to_include
210
+				)
211
+			);
212
+		}
213
+		return $cron_tasks;
214
+	}
215
+
216
+
217
+	/**
218
+	 * Ensure cron tasks are setup (the removal of crons should be done by remove_crons())
219
+	 *
220
+	 * @throws \EE_Error
221
+	 */
222
+	public static function create_cron_tasks()
223
+	{
224
+
225
+		foreach (EEH_Activation::get_cron_tasks('current') as $hook_name => $frequency) {
226
+			if (! wp_next_scheduled($hook_name)) {
227
+				/**
228
+				 * This allows client code to define the initial start timestamp for this schedule.
229
+				 */
230
+				if (is_array($frequency)
231
+					&& count($frequency) === 2
232
+					&& isset($frequency[0], $frequency[1])
233
+				) {
234
+					$start_timestamp = $frequency[0];
235
+					$frequency = $frequency[1];
236
+				} else {
237
+					$start_timestamp = time();
238
+				}
239
+				wp_schedule_event($start_timestamp, $frequency, $hook_name);
240
+			}
241
+		}
242
+
243
+	}
244
+
245
+
246
+	/**
247
+	 * Remove the currently-existing and now-removed cron tasks.
248
+	 *
249
+	 * @param boolean $remove_all whether to only remove the old ones, or remove absolutely ALL the EE ones
250
+	 * @throws \EE_Error
251
+	 */
252
+	public static function remove_cron_tasks($remove_all = true)
253
+	{
254
+		$cron_tasks_to_remove = $remove_all ? 'all' : 'old';
255
+		$crons                = _get_cron_array();
256
+		$crons                = is_array($crons) ? $crons : array();
257
+		/* reminder of what $crons look like:
258 258
          * Top-level keys are timestamps, and their values are arrays.
259 259
          * The 2nd level arrays have keys with each of the cron task hook names to run at that time
260 260
          * and their values are arrays.
@@ -271,912 +271,912 @@  discard block
 block discarded – undo
271 271
          *					...
272 272
          *      ...
273 273
          */
274
-        $ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
275
-        foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
276
-            if (is_array($hooks_to_fire_at_time)) {
277
-                foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
278
-                    if (isset($ee_cron_tasks_to_remove[$hook_name])
279
-                        && is_array($ee_cron_tasks_to_remove[$hook_name])
280
-                    ) {
281
-                        unset($crons[$timestamp][$hook_name]);
282
-                    }
283
-                }
284
-                //also take care of any empty cron timestamps.
285
-                if (empty($hooks_to_fire_at_time)) {
286
-                    unset($crons[$timestamp]);
287
-                }
288
-            }
289
-        }
290
-        _set_cron_array($crons);
291
-    }
292
-
293
-
294
-    /**
295
-     *    CPT_initialization
296
-     *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
297
-     *
298
-     * @access public
299
-     * @static
300
-     * @return void
301
-     */
302
-    public static function CPT_initialization()
303
-    {
304
-        // register Custom Post Types
305
-        EE_Registry::instance()->load_core('Register_CPTs');
306
-        flush_rewrite_rules();
307
-    }
308
-
309
-
310
-
311
-    /**
312
-     *    reset_and_update_config
313
-     * The following code was moved over from EE_Config so that it will no longer run on every request.
314
-     * If there is old calendar config data saved, then it will get converted on activation.
315
-     * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
316
-     *
317
-     * @access public
318
-     * @static
319
-     * @return void
320
-     */
321
-    public static function reset_and_update_config()
322
-    {
323
-        do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
324
-        add_filter(
325
-            'FHEE__EE_Config___load_core_config__config_settings',
326
-            array('EEH_Activation', 'migrate_old_config_data'),
327
-            10,
328
-            3
329
-        );
330
-        //EE_Config::reset();
331
-        if (! EE_Config::logging_enabled()) {
332
-            delete_option(EE_Config::LOG_NAME);
333
-        }
334
-    }
335
-
336
-
337
-    /**
338
-     *    load_calendar_config
339
-     *
340
-     * @access    public
341
-     * @return    void
342
-     */
343
-    public static function load_calendar_config()
344
-    {
345
-        // grab array of all plugin folders and loop thru it
346
-        $plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
347
-        if (empty($plugins)) {
348
-            return;
349
-        }
350
-        foreach ($plugins as $plugin_path) {
351
-            // grab plugin folder name from path
352
-            $plugin = basename($plugin_path);
353
-            // drill down to Espresso plugins
354
-            // then to calendar related plugins
355
-            if (
356
-                strpos($plugin, 'espresso') !== false
357
-                || strpos($plugin, 'Espresso') !== false
358
-                || strpos($plugin, 'ee4') !== false
359
-                || strpos($plugin, 'EE4') !== false
360
-                || strpos($plugin, 'calendar') !== false
361
-            ) {
362
-                // this is what we are looking for
363
-                $calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
364
-                // does it exist in this folder ?
365
-                if (is_readable($calendar_config)) {
366
-                    // YEAH! let's load it
367
-                    require_once($calendar_config);
368
-                }
369
-            }
370
-        }
371
-    }
372
-
373
-
374
-
375
-    /**
376
-     *    _migrate_old_config_data
377
-     *
378
-     * @access    public
379
-     * @param array|stdClass $settings
380
-     * @param string         $config
381
-     * @param \EE_Config     $EE_Config
382
-     * @return \stdClass
383
-     */
384
-    public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
385
-    {
386
-        $convert_from_array = array('addons');
387
-        // in case old settings were saved as an array
388
-        if (is_array($settings) && in_array($config, $convert_from_array)) {
389
-            // convert existing settings to an object
390
-            $config_array = $settings;
391
-            $settings = new stdClass();
392
-            foreach ($config_array as $key => $value) {
393
-                if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
394
-                    $EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
395
-                } else {
396
-                    $settings->{$key} = $value;
397
-                }
398
-            }
399
-            add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
400
-        }
401
-        return $settings;
402
-    }
403
-
404
-
405
-    /**
406
-     * deactivate_event_espresso
407
-     *
408
-     * @access public
409
-     * @static
410
-     * @return void
411
-     */
412
-    public static function deactivate_event_espresso()
413
-    {
414
-        // check permissions
415
-        if (current_user_can('activate_plugins')) {
416
-            deactivate_plugins(EE_PLUGIN_BASENAME, true);
417
-        }
418
-    }
419
-
420
-
421
-
422
-
423
-
424
-    /**
425
-     * verify_default_pages_exist
426
-     *
427
-     * @access public
428
-     * @static
429
-     * @return void
430
-     */
431
-    public static function verify_default_pages_exist()
432
-    {
433
-        $critical_page_problem = false;
434
-        $critical_pages = array(
435
-            array(
436
-                'id'   => 'reg_page_id',
437
-                'name' => __('Registration Checkout', 'event_espresso'),
438
-                'post' => null,
439
-                'code' => 'ESPRESSO_CHECKOUT',
440
-            ),
441
-            array(
442
-                'id'   => 'txn_page_id',
443
-                'name' => __('Transactions', 'event_espresso'),
444
-                'post' => null,
445
-                'code' => 'ESPRESSO_TXN_PAGE',
446
-            ),
447
-            array(
448
-                'id'   => 'thank_you_page_id',
449
-                'name' => __('Thank You', 'event_espresso'),
450
-                'post' => null,
451
-                'code' => 'ESPRESSO_THANK_YOU',
452
-            ),
453
-            array(
454
-                'id'   => 'cancel_page_id',
455
-                'name' => __('Registration Cancelled', 'event_espresso'),
456
-                'post' => null,
457
-                'code' => 'ESPRESSO_CANCELLED',
458
-            ),
459
-        );
460
-        $EE_Core_Config = EE_Registry::instance()->CFG->core;
461
-        foreach ($critical_pages as $critical_page) {
462
-            // is critical page ID set in config ?
463
-            if ($EE_Core_Config->{$critical_page['id']} !== false) {
464
-                // attempt to find post by ID
465
-                $critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
466
-            }
467
-            // no dice?
468
-            if ($critical_page['post'] === null) {
469
-                // attempt to find post by title
470
-                $critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
471
-                // still nothing?
472
-                if ($critical_page['post'] === null) {
473
-                    $critical_page = EEH_Activation::create_critical_page($critical_page);
474
-                    // REALLY? Still nothing ??!?!?
475
-                    if ($critical_page['post'] === null) {
476
-                        $msg = __(
477
-                            'The Event Espresso critical page configuration settings could not be updated.',
478
-                            'event_espresso'
479
-                        );
480
-                        EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
481
-                        break;
482
-                    }
483
-                }
484
-            }
485
-            // check that Post ID matches critical page ID in config
486
-            if (
487
-                isset($critical_page['post']->ID)
488
-                && $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
489
-            ) {
490
-                //update Config with post ID
491
-                $EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
492
-                if (! EE_Config::instance()->update_espresso_config(false, false)) {
493
-                    $msg = __(
494
-                        'The Event Espresso critical page configuration settings could not be updated.',
495
-                        'event_espresso'
496
-                    );
497
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
498
-                }
499
-            }
500
-            $critical_page_problem =
501
-                ! isset($critical_page['post']->post_status)
502
-                || $critical_page['post']->post_status !== 'publish'
503
-                || strpos($critical_page['post']->post_content, $critical_page['code']) === false
504
-                    ? true
505
-                    : $critical_page_problem;
506
-        }
507
-        if ($critical_page_problem) {
508
-            $msg = sprintf(
509
-                __(
510
-                    'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
511
-                    'event_espresso'
512
-                ),
513
-                '<a href="'
514
-                . admin_url('admin.php?page=espresso_general_settings&action=critical_pages')
515
-                . '">'
516
-                . __('Event Espresso Critical Pages Settings', 'event_espresso')
517
-                . '</a>'
518
-            );
519
-            EE_Error::add_persistent_admin_notice('critical_page_problem', $msg);
520
-        }
521
-        if (EE_Error::has_notices()) {
522
-            EE_Error::get_notices(false, true, true);
523
-        }
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     * Returns the first post which uses the specified shortcode
530
-     *
531
-     * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
532
-     *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
533
-     *                             "[ESPRESSO_THANK_YOU"
534
-     *                             (we don't search for the closing shortcode bracket because they might have added
535
-     *                             parameter to the shortcode
536
-     * @return WP_Post or NULl
537
-     */
538
-    public static function get_page_by_ee_shortcode($ee_shortcode)
539
-    {
540
-        global $wpdb;
541
-        $shortcode_and_opening_bracket = '[' . $ee_shortcode;
542
-        $post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
543
-        if ($post_id) {
544
-            return get_post($post_id);
545
-        } else {
546
-            return null;
547
-        }
548
-    }
549
-
550
-
551
-    /**
552
-     *    This function generates a post for critical espresso pages
553
-     *
554
-     * @access public
555
-     * @static
556
-     * @param array $critical_page
557
-     * @return array
558
-     */
559
-    public static function create_critical_page($critical_page)
560
-    {
561
-
562
-        $post_args = array(
563
-            'post_title'     => $critical_page['name'],
564
-            'post_status'    => 'publish',
565
-            'post_type'      => 'page',
566
-            'comment_status' => 'closed',
567
-            'post_content'   => '[' . $critical_page['code'] . ']',
568
-        );
569
-
570
-        $post_id = wp_insert_post($post_args);
571
-        if (! $post_id) {
572
-            $msg = sprintf(
573
-                __('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
574
-                $critical_page['name']
575
-            );
576
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
577
-            return $critical_page;
578
-        }
579
-        // get newly created post's details
580
-        if (! $critical_page['post'] = get_post($post_id)) {
581
-            $msg = sprintf(
582
-                __('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
583
-                $critical_page['name']
584
-            );
585
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
586
-        }
587
-
588
-        return $critical_page;
589
-
590
-    }
591
-
592
-
593
-
594
-
595
-    /**
596
-     * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
597
-     * The role being used to check is filterable.
598
-     *
599
-     * @since  4.6.0
600
-     * @global WPDB $wpdb
601
-     * @return mixed null|int WP_user ID or NULL
602
-     */
603
-    public static function get_default_creator_id()
604
-    {
605
-        global $wpdb;
606
-        if ( ! empty(self::$_default_creator_id)) {
607
-            return self::$_default_creator_id;
608
-        }/**/
609
-        $role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
610
-        //let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
611
-        $pre_filtered_id = apply_filters(
612
-            'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
613
-            false,
614
-            $role_to_check
615
-        );
616
-        if ($pre_filtered_id !== false) {
617
-            return (int)$pre_filtered_id;
618
-        }
619
-        $capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
620
-        $query = $wpdb->prepare(
621
-            "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
622
-            '%' . $role_to_check . '%'
623
-        );
624
-        $user_id = $wpdb->get_var($query);
625
-        $user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
626
-        if ($user_id && (int)$user_id) {
627
-            self::$_default_creator_id = (int)$user_id;
628
-            return self::$_default_creator_id;
629
-        } else {
630
-            return null;
631
-        }
632
-    }
633
-
634
-
635
-
636
-    /**
637
-     * used by EE and EE addons during plugin activation to create tables.
638
-     * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
639
-     * but includes extra logic regarding activations.
640
-     *
641
-     * @access public
642
-     * @static
643
-     * @param string  $table_name              without the $wpdb->prefix
644
-     * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
645
-     *                                         table query)
646
-     * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
647
-     * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
648
-     *                                         and new once this function is done (ie, you really do want to CREATE a
649
-     *                                         table, and expect it to be empty once you're done) leave as FALSE when
650
-     *                                         you just want to verify the table exists and matches this definition
651
-     *                                         (and if it HAS data in it you want to leave it be)
652
-     * @return void
653
-     * @throws EE_Error if there are database errors
654
-     */
655
-    public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
656
-    {
657
-        if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
658
-            return;
659
-        }
660
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
661
-        if ( ! function_exists('dbDelta')) {
662
-            require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
663
-        }
664
-        $tableAnalysis = \EEH_Activation::getTableAnalysis();
665
-        $wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
666
-        // do we need to first delete an existing version of this table ?
667
-        if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
668
-            // ok, delete the table... but ONLY if it's empty
669
-            $deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
670
-            // table is NOT empty, are you SURE you want to delete this table ???
671
-            if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
672
-                \EEH_Activation::getTableManager()->dropTable($wp_table_name);
673
-            } else if ( ! $deleted_safely) {
674
-                // so we should be more cautious rather than just dropping tables so easily
675
-                error_log(
676
-                    sprintf(
677
-                        __(
678
-                            'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
679
-                            'event_espresso'
680
-                        ),
681
-                        $wp_table_name,
682
-                        '<br/>',
683
-                        'espresso_db_update'
684
-                    )
685
-                );
686
-            }
687
-        }
688
-        $engine = str_replace('ENGINE=', '', $engine);
689
-        \EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
690
-    }
691
-
692
-
693
-
694
-    /**
695
-     *    add_column_if_it_doesn't_exist
696
-     *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
697
-     *
698
-     * @access     public
699
-     * @static
700
-     * @deprecated instead use TableManager::addColumn()
701
-     * @param string $table_name  (without "wp_", eg "esp_attendee"
702
-     * @param string $column_name
703
-     * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
704
-     *                            'VARCHAR(10)'
705
-     * @return bool|int
706
-     */
707
-    public static function add_column_if_it_doesnt_exist(
708
-        $table_name,
709
-        $column_name,
710
-        $column_info = 'INT UNSIGNED NOT NULL'
711
-    ) {
712
-        return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
713
-    }
714
-
715
-
716
-    /**
717
-     * get_fields_on_table
718
-     * Gets all the fields on the database table.
719
-     *
720
-     * @access     public
721
-     * @deprecated instead use TableManager::getTableColumns()
722
-     * @static
723
-     * @param string $table_name , without prefixed $wpdb->prefix
724
-     * @return array of database column names
725
-     */
726
-    public static function get_fields_on_table($table_name = null)
727
-    {
728
-        return \EEH_Activation::getTableManager()->getTableColumns($table_name);
729
-    }
730
-
731
-
732
-    /**
733
-     * db_table_is_empty
734
-     *
735
-     * @access     public\
736
-     * @deprecated instead use TableAnalysis::tableIsEmpty()
737
-     * @static
738
-     * @param string $table_name
739
-     * @return bool
740
-     */
741
-    public static function db_table_is_empty($table_name)
742
-    {
743
-        return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
744
-    }
745
-
746
-
747
-    /**
748
-     * delete_db_table_if_empty
749
-     *
750
-     * @access public
751
-     * @static
752
-     * @param string $table_name
753
-     * @return bool | int
754
-     */
755
-    public static function delete_db_table_if_empty($table_name)
756
-    {
757
-        if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
758
-            return \EEH_Activation::getTableManager()->dropTable($table_name);
759
-        }
760
-        return false;
761
-    }
762
-
763
-
764
-    /**
765
-     * delete_unused_db_table
766
-     *
767
-     * @access     public
768
-     * @static
769
-     * @deprecated instead use TableManager::dropTable()
770
-     * @param string $table_name
771
-     * @return bool | int
772
-     */
773
-    public static function delete_unused_db_table($table_name)
774
-    {
775
-        return \EEH_Activation::getTableManager()->dropTable($table_name);
776
-    }
777
-
778
-
779
-    /**
780
-     * drop_index
781
-     *
782
-     * @access     public
783
-     * @static
784
-     * @deprecated instead use TableManager::dropIndex()
785
-     * @param string $table_name
786
-     * @param string $index_name
787
-     * @return bool | int
788
-     */
789
-    public static function drop_index($table_name, $index_name)
790
-    {
791
-        return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
792
-    }
793
-
794
-
795
-
796
-    /**
797
-     * create_database_tables
798
-     *
799
-     * @access public
800
-     * @static
801
-     * @throws EE_Error
802
-     * @return boolean success (whether database is setup properly or not)
803
-     */
804
-    public static function create_database_tables()
805
-    {
806
-        EE_Registry::instance()->load_core('Data_Migration_Manager');
807
-        //find the migration script that sets the database to be compatible with the code
808
-        $dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
809
-        if ($dms_name) {
810
-            $current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
811
-            $current_data_migration_script->set_migrating(false);
812
-            $current_data_migration_script->schema_changes_before_migration();
813
-            $current_data_migration_script->schema_changes_after_migration();
814
-            if ($current_data_migration_script->get_errors()) {
815
-                if (WP_DEBUG) {
816
-                    foreach ($current_data_migration_script->get_errors() as $error) {
817
-                        EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
818
-                    }
819
-                } else {
820
-                    EE_Error::add_error(
821
-                        __(
822
-                            'There were errors creating the Event Espresso database tables and Event Espresso has been 
274
+		$ee_cron_tasks_to_remove = EEH_Activation::get_cron_tasks($cron_tasks_to_remove);
275
+		foreach ($crons as $timestamp => $hooks_to_fire_at_time) {
276
+			if (is_array($hooks_to_fire_at_time)) {
277
+				foreach ($hooks_to_fire_at_time as $hook_name => $hook_actions) {
278
+					if (isset($ee_cron_tasks_to_remove[$hook_name])
279
+						&& is_array($ee_cron_tasks_to_remove[$hook_name])
280
+					) {
281
+						unset($crons[$timestamp][$hook_name]);
282
+					}
283
+				}
284
+				//also take care of any empty cron timestamps.
285
+				if (empty($hooks_to_fire_at_time)) {
286
+					unset($crons[$timestamp]);
287
+				}
288
+			}
289
+		}
290
+		_set_cron_array($crons);
291
+	}
292
+
293
+
294
+	/**
295
+	 *    CPT_initialization
296
+	 *    registers all EE CPTs ( Custom Post Types ) then flushes rewrite rules so that all endpoints exist
297
+	 *
298
+	 * @access public
299
+	 * @static
300
+	 * @return void
301
+	 */
302
+	public static function CPT_initialization()
303
+	{
304
+		// register Custom Post Types
305
+		EE_Registry::instance()->load_core('Register_CPTs');
306
+		flush_rewrite_rules();
307
+	}
308
+
309
+
310
+
311
+	/**
312
+	 *    reset_and_update_config
313
+	 * The following code was moved over from EE_Config so that it will no longer run on every request.
314
+	 * If there is old calendar config data saved, then it will get converted on activation.
315
+	 * This was basically a DMS before we had DMS's, and will get removed after a few more versions.
316
+	 *
317
+	 * @access public
318
+	 * @static
319
+	 * @return void
320
+	 */
321
+	public static function reset_and_update_config()
322
+	{
323
+		do_action('AHEE__EE_Config___load_core_config__start', array('EEH_Activation', 'load_calendar_config'));
324
+		add_filter(
325
+			'FHEE__EE_Config___load_core_config__config_settings',
326
+			array('EEH_Activation', 'migrate_old_config_data'),
327
+			10,
328
+			3
329
+		);
330
+		//EE_Config::reset();
331
+		if (! EE_Config::logging_enabled()) {
332
+			delete_option(EE_Config::LOG_NAME);
333
+		}
334
+	}
335
+
336
+
337
+	/**
338
+	 *    load_calendar_config
339
+	 *
340
+	 * @access    public
341
+	 * @return    void
342
+	 */
343
+	public static function load_calendar_config()
344
+	{
345
+		// grab array of all plugin folders and loop thru it
346
+		$plugins = glob(WP_PLUGIN_DIR . DS . '*', GLOB_ONLYDIR);
347
+		if (empty($plugins)) {
348
+			return;
349
+		}
350
+		foreach ($plugins as $plugin_path) {
351
+			// grab plugin folder name from path
352
+			$plugin = basename($plugin_path);
353
+			// drill down to Espresso plugins
354
+			// then to calendar related plugins
355
+			if (
356
+				strpos($plugin, 'espresso') !== false
357
+				|| strpos($plugin, 'Espresso') !== false
358
+				|| strpos($plugin, 'ee4') !== false
359
+				|| strpos($plugin, 'EE4') !== false
360
+				|| strpos($plugin, 'calendar') !== false
361
+			) {
362
+				// this is what we are looking for
363
+				$calendar_config = $plugin_path . DS . 'EE_Calendar_Config.php';
364
+				// does it exist in this folder ?
365
+				if (is_readable($calendar_config)) {
366
+					// YEAH! let's load it
367
+					require_once($calendar_config);
368
+				}
369
+			}
370
+		}
371
+	}
372
+
373
+
374
+
375
+	/**
376
+	 *    _migrate_old_config_data
377
+	 *
378
+	 * @access    public
379
+	 * @param array|stdClass $settings
380
+	 * @param string         $config
381
+	 * @param \EE_Config     $EE_Config
382
+	 * @return \stdClass
383
+	 */
384
+	public static function migrate_old_config_data($settings = array(), $config = '', EE_Config $EE_Config)
385
+	{
386
+		$convert_from_array = array('addons');
387
+		// in case old settings were saved as an array
388
+		if (is_array($settings) && in_array($config, $convert_from_array)) {
389
+			// convert existing settings to an object
390
+			$config_array = $settings;
391
+			$settings = new stdClass();
392
+			foreach ($config_array as $key => $value) {
393
+				if ($key === 'calendar' && class_exists('EE_Calendar_Config')) {
394
+					$EE_Config->set_config('addons', 'EE_Calendar', 'EE_Calendar_Config', $value);
395
+				} else {
396
+					$settings->{$key} = $value;
397
+				}
398
+			}
399
+			add_filter('FHEE__EE_Config___load_core_config__update_espresso_config', '__return_true');
400
+		}
401
+		return $settings;
402
+	}
403
+
404
+
405
+	/**
406
+	 * deactivate_event_espresso
407
+	 *
408
+	 * @access public
409
+	 * @static
410
+	 * @return void
411
+	 */
412
+	public static function deactivate_event_espresso()
413
+	{
414
+		// check permissions
415
+		if (current_user_can('activate_plugins')) {
416
+			deactivate_plugins(EE_PLUGIN_BASENAME, true);
417
+		}
418
+	}
419
+
420
+
421
+
422
+
423
+
424
+	/**
425
+	 * verify_default_pages_exist
426
+	 *
427
+	 * @access public
428
+	 * @static
429
+	 * @return void
430
+	 */
431
+	public static function verify_default_pages_exist()
432
+	{
433
+		$critical_page_problem = false;
434
+		$critical_pages = array(
435
+			array(
436
+				'id'   => 'reg_page_id',
437
+				'name' => __('Registration Checkout', 'event_espresso'),
438
+				'post' => null,
439
+				'code' => 'ESPRESSO_CHECKOUT',
440
+			),
441
+			array(
442
+				'id'   => 'txn_page_id',
443
+				'name' => __('Transactions', 'event_espresso'),
444
+				'post' => null,
445
+				'code' => 'ESPRESSO_TXN_PAGE',
446
+			),
447
+			array(
448
+				'id'   => 'thank_you_page_id',
449
+				'name' => __('Thank You', 'event_espresso'),
450
+				'post' => null,
451
+				'code' => 'ESPRESSO_THANK_YOU',
452
+			),
453
+			array(
454
+				'id'   => 'cancel_page_id',
455
+				'name' => __('Registration Cancelled', 'event_espresso'),
456
+				'post' => null,
457
+				'code' => 'ESPRESSO_CANCELLED',
458
+			),
459
+		);
460
+		$EE_Core_Config = EE_Registry::instance()->CFG->core;
461
+		foreach ($critical_pages as $critical_page) {
462
+			// is critical page ID set in config ?
463
+			if ($EE_Core_Config->{$critical_page['id']} !== false) {
464
+				// attempt to find post by ID
465
+				$critical_page['post'] = get_post($EE_Core_Config->{$critical_page['id']});
466
+			}
467
+			// no dice?
468
+			if ($critical_page['post'] === null) {
469
+				// attempt to find post by title
470
+				$critical_page['post'] = self::get_page_by_ee_shortcode($critical_page['code']);
471
+				// still nothing?
472
+				if ($critical_page['post'] === null) {
473
+					$critical_page = EEH_Activation::create_critical_page($critical_page);
474
+					// REALLY? Still nothing ??!?!?
475
+					if ($critical_page['post'] === null) {
476
+						$msg = __(
477
+							'The Event Espresso critical page configuration settings could not be updated.',
478
+							'event_espresso'
479
+						);
480
+						EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
481
+						break;
482
+					}
483
+				}
484
+			}
485
+			// check that Post ID matches critical page ID in config
486
+			if (
487
+				isset($critical_page['post']->ID)
488
+				&& $critical_page['post']->ID !== $EE_Core_Config->{$critical_page['id']}
489
+			) {
490
+				//update Config with post ID
491
+				$EE_Core_Config->{$critical_page['id']} = $critical_page['post']->ID;
492
+				if (! EE_Config::instance()->update_espresso_config(false, false)) {
493
+					$msg = __(
494
+						'The Event Espresso critical page configuration settings could not be updated.',
495
+						'event_espresso'
496
+					);
497
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
498
+				}
499
+			}
500
+			$critical_page_problem =
501
+				! isset($critical_page['post']->post_status)
502
+				|| $critical_page['post']->post_status !== 'publish'
503
+				|| strpos($critical_page['post']->post_content, $critical_page['code']) === false
504
+					? true
505
+					: $critical_page_problem;
506
+		}
507
+		if ($critical_page_problem) {
508
+			$msg = sprintf(
509
+				__(
510
+					'A potential issue has been detected with one or more of your Event Espresso pages. Go to %s to view your Event Espresso pages.',
511
+					'event_espresso'
512
+				),
513
+				'<a href="'
514
+				. admin_url('admin.php?page=espresso_general_settings&action=critical_pages')
515
+				. '">'
516
+				. __('Event Espresso Critical Pages Settings', 'event_espresso')
517
+				. '</a>'
518
+			);
519
+			EE_Error::add_persistent_admin_notice('critical_page_problem', $msg);
520
+		}
521
+		if (EE_Error::has_notices()) {
522
+			EE_Error::get_notices(false, true, true);
523
+		}
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 * Returns the first post which uses the specified shortcode
530
+	 *
531
+	 * @param string $ee_shortcode usually one of the critical pages shortcodes, eg
532
+	 *                             ESPRESSO_THANK_YOU. So we will search fora post with the content
533
+	 *                             "[ESPRESSO_THANK_YOU"
534
+	 *                             (we don't search for the closing shortcode bracket because they might have added
535
+	 *                             parameter to the shortcode
536
+	 * @return WP_Post or NULl
537
+	 */
538
+	public static function get_page_by_ee_shortcode($ee_shortcode)
539
+	{
540
+		global $wpdb;
541
+		$shortcode_and_opening_bracket = '[' . $ee_shortcode;
542
+		$post_id = $wpdb->get_var("SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE '%$shortcode_and_opening_bracket%' LIMIT 1");
543
+		if ($post_id) {
544
+			return get_post($post_id);
545
+		} else {
546
+			return null;
547
+		}
548
+	}
549
+
550
+
551
+	/**
552
+	 *    This function generates a post for critical espresso pages
553
+	 *
554
+	 * @access public
555
+	 * @static
556
+	 * @param array $critical_page
557
+	 * @return array
558
+	 */
559
+	public static function create_critical_page($critical_page)
560
+	{
561
+
562
+		$post_args = array(
563
+			'post_title'     => $critical_page['name'],
564
+			'post_status'    => 'publish',
565
+			'post_type'      => 'page',
566
+			'comment_status' => 'closed',
567
+			'post_content'   => '[' . $critical_page['code'] . ']',
568
+		);
569
+
570
+		$post_id = wp_insert_post($post_args);
571
+		if (! $post_id) {
572
+			$msg = sprintf(
573
+				__('The Event Espresso  critical page entitled "%s" could not be created.', 'event_espresso'),
574
+				$critical_page['name']
575
+			);
576
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
577
+			return $critical_page;
578
+		}
579
+		// get newly created post's details
580
+		if (! $critical_page['post'] = get_post($post_id)) {
581
+			$msg = sprintf(
582
+				__('The Event Espresso critical page entitled "%s" could not be retrieved.', 'event_espresso'),
583
+				$critical_page['name']
584
+			);
585
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
586
+		}
587
+
588
+		return $critical_page;
589
+
590
+	}
591
+
592
+
593
+
594
+
595
+	/**
596
+	 * Tries to find the oldest admin for this site.  If there are no admins for this site then return NULL.
597
+	 * The role being used to check is filterable.
598
+	 *
599
+	 * @since  4.6.0
600
+	 * @global WPDB $wpdb
601
+	 * @return mixed null|int WP_user ID or NULL
602
+	 */
603
+	public static function get_default_creator_id()
604
+	{
605
+		global $wpdb;
606
+		if ( ! empty(self::$_default_creator_id)) {
607
+			return self::$_default_creator_id;
608
+		}/**/
609
+		$role_to_check = apply_filters('FHEE__EEH_Activation__get_default_creator_id__role_to_check', 'administrator');
610
+		//let's allow pre_filtering for early exits by alternative methods for getting id.  We check for truthy result and if so then exit early.
611
+		$pre_filtered_id = apply_filters(
612
+			'FHEE__EEH_Activation__get_default_creator_id__pre_filtered_id',
613
+			false,
614
+			$role_to_check
615
+		);
616
+		if ($pre_filtered_id !== false) {
617
+			return (int)$pre_filtered_id;
618
+		}
619
+		$capabilities_key = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('capabilities');
620
+		$query = $wpdb->prepare(
621
+			"SELECT user_id FROM $wpdb->usermeta WHERE meta_key = '$capabilities_key' AND meta_value LIKE %s ORDER BY user_id ASC LIMIT 0,1",
622
+			'%' . $role_to_check . '%'
623
+		);
624
+		$user_id = $wpdb->get_var($query);
625
+		$user_id = apply_filters('FHEE__EEH_Activation_Helper__get_default_creator_id__user_id', $user_id);
626
+		if ($user_id && (int)$user_id) {
627
+			self::$_default_creator_id = (int)$user_id;
628
+			return self::$_default_creator_id;
629
+		} else {
630
+			return null;
631
+		}
632
+	}
633
+
634
+
635
+
636
+	/**
637
+	 * used by EE and EE addons during plugin activation to create tables.
638
+	 * Its a wrapper for EventEspresso\core\services\database\TableManager::createTable,
639
+	 * but includes extra logic regarding activations.
640
+	 *
641
+	 * @access public
642
+	 * @static
643
+	 * @param string  $table_name              without the $wpdb->prefix
644
+	 * @param string  $sql                     SQL for creating the table (contents between brackets in an SQL create
645
+	 *                                         table query)
646
+	 * @param string  $engine                  like 'ENGINE=MyISAM' or 'ENGINE=InnoDB'
647
+	 * @param boolean $drop_pre_existing_table set to TRUE when you want to make SURE the table is completely empty
648
+	 *                                         and new once this function is done (ie, you really do want to CREATE a
649
+	 *                                         table, and expect it to be empty once you're done) leave as FALSE when
650
+	 *                                         you just want to verify the table exists and matches this definition
651
+	 *                                         (and if it HAS data in it you want to leave it be)
652
+	 * @return void
653
+	 * @throws EE_Error if there are database errors
654
+	 */
655
+	public static function create_table($table_name, $sql, $engine = 'ENGINE=MyISAM ', $drop_pre_existing_table = false)
656
+	{
657
+		if (apply_filters('FHEE__EEH_Activation__create_table__short_circuit', false, $table_name, $sql)) {
658
+			return;
659
+		}
660
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
661
+		if ( ! function_exists('dbDelta')) {
662
+			require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
663
+		}
664
+		$tableAnalysis = \EEH_Activation::getTableAnalysis();
665
+		$wp_table_name = $tableAnalysis->ensureTableNameHasPrefix($table_name);
666
+		// do we need to first delete an existing version of this table ?
667
+		if ($drop_pre_existing_table && $tableAnalysis->tableExists($wp_table_name)) {
668
+			// ok, delete the table... but ONLY if it's empty
669
+			$deleted_safely = EEH_Activation::delete_db_table_if_empty($wp_table_name);
670
+			// table is NOT empty, are you SURE you want to delete this table ???
671
+			if ( ! $deleted_safely && defined('EE_DROP_BAD_TABLES') && EE_DROP_BAD_TABLES) {
672
+				\EEH_Activation::getTableManager()->dropTable($wp_table_name);
673
+			} else if ( ! $deleted_safely) {
674
+				// so we should be more cautious rather than just dropping tables so easily
675
+				error_log(
676
+					sprintf(
677
+						__(
678
+							'It appears that database table "%1$s" exists when it shouldn\'t, and therefore may contain erroneous data. If you have previously restored your database from a backup that didn\'t remove the old tables, then we recommend: %2$s 1. create a new COMPLETE backup of your database, %2$s 2. delete ALL tables from your database, %2$s 3. restore to your previous backup. %2$s If, however, you have not restored to a backup, then somehow your "%3$s" WordPress option could not be read. You can probably ignore this message, but should investigate why that option is being removed.',
679
+							'event_espresso'
680
+						),
681
+						$wp_table_name,
682
+						'<br/>',
683
+						'espresso_db_update'
684
+					)
685
+				);
686
+			}
687
+		}
688
+		$engine = str_replace('ENGINE=', '', $engine);
689
+		\EEH_Activation::getTableManager()->createTable($table_name, $sql, $engine);
690
+	}
691
+
692
+
693
+
694
+	/**
695
+	 *    add_column_if_it_doesn't_exist
696
+	 *    Checks if this column already exists on the specified table. Handy for addons which want to add a column
697
+	 *
698
+	 * @access     public
699
+	 * @static
700
+	 * @deprecated instead use TableManager::addColumn()
701
+	 * @param string $table_name  (without "wp_", eg "esp_attendee"
702
+	 * @param string $column_name
703
+	 * @param string $column_info if your SQL were 'ALTER TABLE table_name ADD price VARCHAR(10)', this would be
704
+	 *                            'VARCHAR(10)'
705
+	 * @return bool|int
706
+	 */
707
+	public static function add_column_if_it_doesnt_exist(
708
+		$table_name,
709
+		$column_name,
710
+		$column_info = 'INT UNSIGNED NOT NULL'
711
+	) {
712
+		return \EEH_Activation::getTableManager()->addColumn($table_name, $column_name, $column_info);
713
+	}
714
+
715
+
716
+	/**
717
+	 * get_fields_on_table
718
+	 * Gets all the fields on the database table.
719
+	 *
720
+	 * @access     public
721
+	 * @deprecated instead use TableManager::getTableColumns()
722
+	 * @static
723
+	 * @param string $table_name , without prefixed $wpdb->prefix
724
+	 * @return array of database column names
725
+	 */
726
+	public static function get_fields_on_table($table_name = null)
727
+	{
728
+		return \EEH_Activation::getTableManager()->getTableColumns($table_name);
729
+	}
730
+
731
+
732
+	/**
733
+	 * db_table_is_empty
734
+	 *
735
+	 * @access     public\
736
+	 * @deprecated instead use TableAnalysis::tableIsEmpty()
737
+	 * @static
738
+	 * @param string $table_name
739
+	 * @return bool
740
+	 */
741
+	public static function db_table_is_empty($table_name)
742
+	{
743
+		return \EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name);
744
+	}
745
+
746
+
747
+	/**
748
+	 * delete_db_table_if_empty
749
+	 *
750
+	 * @access public
751
+	 * @static
752
+	 * @param string $table_name
753
+	 * @return bool | int
754
+	 */
755
+	public static function delete_db_table_if_empty($table_name)
756
+	{
757
+		if (\EEH_Activation::getTableAnalysis()->tableIsEmpty($table_name)) {
758
+			return \EEH_Activation::getTableManager()->dropTable($table_name);
759
+		}
760
+		return false;
761
+	}
762
+
763
+
764
+	/**
765
+	 * delete_unused_db_table
766
+	 *
767
+	 * @access     public
768
+	 * @static
769
+	 * @deprecated instead use TableManager::dropTable()
770
+	 * @param string $table_name
771
+	 * @return bool | int
772
+	 */
773
+	public static function delete_unused_db_table($table_name)
774
+	{
775
+		return \EEH_Activation::getTableManager()->dropTable($table_name);
776
+	}
777
+
778
+
779
+	/**
780
+	 * drop_index
781
+	 *
782
+	 * @access     public
783
+	 * @static
784
+	 * @deprecated instead use TableManager::dropIndex()
785
+	 * @param string $table_name
786
+	 * @param string $index_name
787
+	 * @return bool | int
788
+	 */
789
+	public static function drop_index($table_name, $index_name)
790
+	{
791
+		return \EEH_Activation::getTableManager()->dropIndex($table_name, $index_name);
792
+	}
793
+
794
+
795
+
796
+	/**
797
+	 * create_database_tables
798
+	 *
799
+	 * @access public
800
+	 * @static
801
+	 * @throws EE_Error
802
+	 * @return boolean success (whether database is setup properly or not)
803
+	 */
804
+	public static function create_database_tables()
805
+	{
806
+		EE_Registry::instance()->load_core('Data_Migration_Manager');
807
+		//find the migration script that sets the database to be compatible with the code
808
+		$dms_name = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms();
809
+		if ($dms_name) {
810
+			$current_data_migration_script = EE_Registry::instance()->load_dms($dms_name);
811
+			$current_data_migration_script->set_migrating(false);
812
+			$current_data_migration_script->schema_changes_before_migration();
813
+			$current_data_migration_script->schema_changes_after_migration();
814
+			if ($current_data_migration_script->get_errors()) {
815
+				if (WP_DEBUG) {
816
+					foreach ($current_data_migration_script->get_errors() as $error) {
817
+						EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
818
+					}
819
+				} else {
820
+					EE_Error::add_error(
821
+						__(
822
+							'There were errors creating the Event Espresso database tables and Event Espresso has been 
823 823
                             deactivated. To view the errors, please enable WP_DEBUG in your wp-config.php file.',
824
-                            'event_espresso'
825
-                        )
826
-                    );
827
-                }
828
-                return false;
829
-            }
830
-            EE_Data_Migration_Manager::instance()->update_current_database_state_to();
831
-        } else {
832
-            EE_Error::add_error(
833
-                __(
834
-                    'Could not determine most up-to-date data migration script from which to pull database schema
824
+							'event_espresso'
825
+						)
826
+					);
827
+				}
828
+				return false;
829
+			}
830
+			EE_Data_Migration_Manager::instance()->update_current_database_state_to();
831
+		} else {
832
+			EE_Error::add_error(
833
+				__(
834
+					'Could not determine most up-to-date data migration script from which to pull database schema
835 835
                      structure. So database is probably not setup properly',
836
-                    'event_espresso'
837
-                ),
838
-                __FILE__,
839
-                __FUNCTION__,
840
-                __LINE__
841
-            );
842
-            return false;
843
-        }
844
-        return true;
845
-    }
846
-
847
-
848
-
849
-    /**
850
-     * initialize_system_questions
851
-     *
852
-     * @access public
853
-     * @static
854
-     * @return void
855
-     */
856
-    public static function initialize_system_questions()
857
-    {
858
-        // QUESTION GROUPS
859
-        global $wpdb;
860
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
861
-        $SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
862
-        // what we have
863
-        $question_groups = $wpdb->get_col($SQL);
864
-        // check the response
865
-        $question_groups = is_array($question_groups) ? $question_groups : array();
866
-        // what we should have
867
-        $QSG_systems = array(1, 2);
868
-        // loop thru what we should have and compare to what we have
869
-        foreach ($QSG_systems as $QSG_system) {
870
-            // reset values array
871
-            $QSG_values = array();
872
-            // if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
873
-            if (! in_array("$QSG_system", $question_groups)) {
874
-                // add it
875
-                switch ($QSG_system) {
876
-                    case 1:
877
-                        $QSG_values = array(
878
-                            'QSG_name'            => __('Personal Information', 'event_espresso'),
879
-                            'QSG_identifier'      => 'personal-information-' . time(),
880
-                            'QSG_desc'            => '',
881
-                            'QSG_order'           => 1,
882
-                            'QSG_show_group_name' => 1,
883
-                            'QSG_show_group_desc' => 1,
884
-                            'QSG_system'          => EEM_Question_Group::system_personal,
885
-                            'QSG_deleted'         => 0,
886
-                        );
887
-                        break;
888
-                    case 2:
889
-                        $QSG_values = array(
890
-                            'QSG_name'            => __('Address Information', 'event_espresso'),
891
-                            'QSG_identifier'      => 'address-information-' . time(),
892
-                            'QSG_desc'            => '',
893
-                            'QSG_order'           => 2,
894
-                            'QSG_show_group_name' => 1,
895
-                            'QSG_show_group_desc' => 1,
896
-                            'QSG_system'          => EEM_Question_Group::system_address,
897
-                            'QSG_deleted'         => 0,
898
-                        );
899
-                        break;
900
-                }
901
-                // make sure we have some values before inserting them
902
-                if (! empty($QSG_values)) {
903
-                    // insert system question
904
-                    $wpdb->insert(
905
-                        $table_name,
906
-                        $QSG_values,
907
-                        array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
908
-                    );
909
-                    $QSG_IDs[$QSG_system] = $wpdb->insert_id;
910
-                }
911
-            }
912
-        }
913
-        // QUESTIONS
914
-        global $wpdb;
915
-        $table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
916
-        $SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
917
-        // what we have
918
-        $questions = $wpdb->get_col($SQL);
919
-        // what we should have
920
-        $QST_systems = array(
921
-            'fname',
922
-            'lname',
923
-            'email',
924
-            'address',
925
-            'address2',
926
-            'city',
927
-            'country',
928
-            'state',
929
-            'zip',
930
-            'phone',
931
-        );
932
-        $order_for_group_1 = 1;
933
-        $order_for_group_2 = 1;
934
-        // loop thru what we should have and compare to what we have
935
-        foreach ($QST_systems as $QST_system) {
936
-            // reset values array
937
-            $QST_values = array();
938
-            // if we don't have what we should have
939
-            if (! in_array($QST_system, $questions)) {
940
-                // add it
941
-                switch ($QST_system) {
942
-                    case 'fname':
943
-                        $QST_values = array(
944
-                            'QST_display_text'  => __('First Name', 'event_espresso'),
945
-                            'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
946
-                            'QST_system'        => 'fname',
947
-                            'QST_type'          => 'TEXT',
948
-                            'QST_required'      => 1,
949
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
950
-                            'QST_order'         => 1,
951
-                            'QST_admin_only'    => 0,
952
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
953
-                            'QST_wp_user'       => self::get_default_creator_id(),
954
-                            'QST_deleted'       => 0,
955
-                        );
956
-                        break;
957
-                    case 'lname':
958
-                        $QST_values = array(
959
-                            'QST_display_text'  => __('Last Name', 'event_espresso'),
960
-                            'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
961
-                            'QST_system'        => 'lname',
962
-                            'QST_type'          => 'TEXT',
963
-                            'QST_required'      => 1,
964
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
965
-                            'QST_order'         => 2,
966
-                            'QST_admin_only'    => 0,
967
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
968
-                            'QST_wp_user'       => self::get_default_creator_id(),
969
-                            'QST_deleted'       => 0,
970
-                        );
971
-                        break;
972
-                    case 'email':
973
-                        $QST_values = array(
974
-                            'QST_display_text'  => __('Email Address', 'event_espresso'),
975
-                            'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
976
-                            'QST_system'        => 'email',
977
-                            'QST_type'          => 'EMAIL',
978
-                            'QST_required'      => 1,
979
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
980
-                            'QST_order'         => 3,
981
-                            'QST_admin_only'    => 0,
982
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
983
-                            'QST_wp_user'       => self::get_default_creator_id(),
984
-                            'QST_deleted'       => 0,
985
-                        );
986
-                        break;
987
-                    case 'address':
988
-                        $QST_values = array(
989
-                            'QST_display_text'  => __('Address', 'event_espresso'),
990
-                            'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
991
-                            'QST_system'        => 'address',
992
-                            'QST_type'          => 'TEXT',
993
-                            'QST_required'      => 0,
994
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
995
-                            'QST_order'         => 4,
996
-                            'QST_admin_only'    => 0,
997
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
998
-                            'QST_wp_user'       => self::get_default_creator_id(),
999
-                            'QST_deleted'       => 0,
1000
-                        );
1001
-                        break;
1002
-                    case 'address2':
1003
-                        $QST_values = array(
1004
-                            'QST_display_text'  => __('Address2', 'event_espresso'),
1005
-                            'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
1006
-                            'QST_system'        => 'address2',
1007
-                            'QST_type'          => 'TEXT',
1008
-                            'QST_required'      => 0,
1009
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1010
-                            'QST_order'         => 5,
1011
-                            'QST_admin_only'    => 0,
1012
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1013
-                            'QST_wp_user'       => self::get_default_creator_id(),
1014
-                            'QST_deleted'       => 0,
1015
-                        );
1016
-                        break;
1017
-                    case 'city':
1018
-                        $QST_values = array(
1019
-                            'QST_display_text'  => __('City', 'event_espresso'),
1020
-                            'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1021
-                            'QST_system'        => 'city',
1022
-                            'QST_type'          => 'TEXT',
1023
-                            'QST_required'      => 0,
1024
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1025
-                            'QST_order'         => 6,
1026
-                            'QST_admin_only'    => 0,
1027
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1028
-                            'QST_wp_user'       => self::get_default_creator_id(),
1029
-                            'QST_deleted'       => 0,
1030
-                        );
1031
-                        break;
1032
-                    case 'country':
1033
-                        $QST_values = array(
1034
-                            'QST_display_text'  => __('Country', 'event_espresso'),
1035
-                            'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1036
-                            'QST_system'        => 'country',
1037
-                            'QST_type'          => 'COUNTRY',
1038
-                            'QST_required'      => 0,
1039
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1040
-                            'QST_order'         => 7,
1041
-                            'QST_admin_only'    => 0,
1042
-                            'QST_wp_user'       => self::get_default_creator_id(),
1043
-                            'QST_deleted'       => 0,
1044
-                        );
1045
-                        break;
1046
-                    case 'state':
1047
-                        $QST_values = array(
1048
-                            'QST_display_text'  => __('State/Province', 'event_espresso'),
1049
-                            'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1050
-                            'QST_system'        => 'state',
1051
-                            'QST_type'          => 'STATE',
1052
-                            'QST_required'      => 0,
1053
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1054
-                            'QST_order'         => 8,
1055
-                            'QST_admin_only'    => 0,
1056
-                            'QST_wp_user'       => self::get_default_creator_id(),
1057
-                            'QST_deleted'       => 0,
1058
-                        );
1059
-                        break;
1060
-                    case 'zip':
1061
-                        $QST_values = array(
1062
-                            'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1063
-                            'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1064
-                            'QST_system'        => 'zip',
1065
-                            'QST_type'          => 'TEXT',
1066
-                            'QST_required'      => 0,
1067
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1068
-                            'QST_order'         => 9,
1069
-                            'QST_admin_only'    => 0,
1070
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1071
-                            'QST_wp_user'       => self::get_default_creator_id(),
1072
-                            'QST_deleted'       => 0,
1073
-                        );
1074
-                        break;
1075
-                    case 'phone':
1076
-                        $QST_values = array(
1077
-                            'QST_display_text'  => __('Phone Number', 'event_espresso'),
1078
-                            'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1079
-                            'QST_system'        => 'phone',
1080
-                            'QST_type'          => 'TEXT',
1081
-                            'QST_required'      => 0,
1082
-                            'QST_required_text' => __('This field is required', 'event_espresso'),
1083
-                            'QST_order'         => 10,
1084
-                            'QST_admin_only'    => 0,
1085
-                            'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1086
-                            'QST_wp_user'       => self::get_default_creator_id(),
1087
-                            'QST_deleted'       => 0,
1088
-                        );
1089
-                        break;
1090
-                }
1091
-                if (! empty($QST_values)) {
1092
-                    // insert system question
1093
-                    $wpdb->insert(
1094
-                        $table_name,
1095
-                        $QST_values,
1096
-                        array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1097
-                    );
1098
-                    $QST_ID = $wpdb->insert_id;
1099
-                    // QUESTION GROUP QUESTIONS
1100
-                    if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1101
-                        $system_question_we_want = EEM_Question_Group::system_personal;
1102
-                    } else {
1103
-                        $system_question_we_want = EEM_Question_Group::system_address;
1104
-                    }
1105
-                    if (isset($QSG_IDs[$system_question_we_want])) {
1106
-                        $QSG_ID = $QSG_IDs[$system_question_we_want];
1107
-                    } else {
1108
-                        $id_col = EEM_Question_Group::instance()
1109
-                                                    ->get_col(array(array('QSG_system' => $system_question_we_want)));
1110
-                        if (is_array($id_col)) {
1111
-                            $QSG_ID = reset($id_col);
1112
-                        } else {
1113
-                            //ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1114
-                            EE_Log::instance()->log(
1115
-                                __FILE__,
1116
-                                __FUNCTION__,
1117
-                                sprintf(
1118
-                                    __(
1119
-                                        'Could not associate question %1$s to a question group because no system question
836
+					'event_espresso'
837
+				),
838
+				__FILE__,
839
+				__FUNCTION__,
840
+				__LINE__
841
+			);
842
+			return false;
843
+		}
844
+		return true;
845
+	}
846
+
847
+
848
+
849
+	/**
850
+	 * initialize_system_questions
851
+	 *
852
+	 * @access public
853
+	 * @static
854
+	 * @return void
855
+	 */
856
+	public static function initialize_system_questions()
857
+	{
858
+		// QUESTION GROUPS
859
+		global $wpdb;
860
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group');
861
+		$SQL = "SELECT QSG_system FROM $table_name WHERE QSG_system != 0";
862
+		// what we have
863
+		$question_groups = $wpdb->get_col($SQL);
864
+		// check the response
865
+		$question_groups = is_array($question_groups) ? $question_groups : array();
866
+		// what we should have
867
+		$QSG_systems = array(1, 2);
868
+		// loop thru what we should have and compare to what we have
869
+		foreach ($QSG_systems as $QSG_system) {
870
+			// reset values array
871
+			$QSG_values = array();
872
+			// if we don't have what we should have (but use $QST_system as as string because that's what we got from the db)
873
+			if (! in_array("$QSG_system", $question_groups)) {
874
+				// add it
875
+				switch ($QSG_system) {
876
+					case 1:
877
+						$QSG_values = array(
878
+							'QSG_name'            => __('Personal Information', 'event_espresso'),
879
+							'QSG_identifier'      => 'personal-information-' . time(),
880
+							'QSG_desc'            => '',
881
+							'QSG_order'           => 1,
882
+							'QSG_show_group_name' => 1,
883
+							'QSG_show_group_desc' => 1,
884
+							'QSG_system'          => EEM_Question_Group::system_personal,
885
+							'QSG_deleted'         => 0,
886
+						);
887
+						break;
888
+					case 2:
889
+						$QSG_values = array(
890
+							'QSG_name'            => __('Address Information', 'event_espresso'),
891
+							'QSG_identifier'      => 'address-information-' . time(),
892
+							'QSG_desc'            => '',
893
+							'QSG_order'           => 2,
894
+							'QSG_show_group_name' => 1,
895
+							'QSG_show_group_desc' => 1,
896
+							'QSG_system'          => EEM_Question_Group::system_address,
897
+							'QSG_deleted'         => 0,
898
+						);
899
+						break;
900
+				}
901
+				// make sure we have some values before inserting them
902
+				if (! empty($QSG_values)) {
903
+					// insert system question
904
+					$wpdb->insert(
905
+						$table_name,
906
+						$QSG_values,
907
+						array('%s', '%s', '%s', '%d', '%d', '%d', '%d', '%d')
908
+					);
909
+					$QSG_IDs[$QSG_system] = $wpdb->insert_id;
910
+				}
911
+			}
912
+		}
913
+		// QUESTIONS
914
+		global $wpdb;
915
+		$table_name = \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question');
916
+		$SQL = "SELECT QST_system FROM $table_name WHERE QST_system != ''";
917
+		// what we have
918
+		$questions = $wpdb->get_col($SQL);
919
+		// what we should have
920
+		$QST_systems = array(
921
+			'fname',
922
+			'lname',
923
+			'email',
924
+			'address',
925
+			'address2',
926
+			'city',
927
+			'country',
928
+			'state',
929
+			'zip',
930
+			'phone',
931
+		);
932
+		$order_for_group_1 = 1;
933
+		$order_for_group_2 = 1;
934
+		// loop thru what we should have and compare to what we have
935
+		foreach ($QST_systems as $QST_system) {
936
+			// reset values array
937
+			$QST_values = array();
938
+			// if we don't have what we should have
939
+			if (! in_array($QST_system, $questions)) {
940
+				// add it
941
+				switch ($QST_system) {
942
+					case 'fname':
943
+						$QST_values = array(
944
+							'QST_display_text'  => __('First Name', 'event_espresso'),
945
+							'QST_admin_label'   => __('First Name - System Question', 'event_espresso'),
946
+							'QST_system'        => 'fname',
947
+							'QST_type'          => 'TEXT',
948
+							'QST_required'      => 1,
949
+							'QST_required_text' => __('This field is required', 'event_espresso'),
950
+							'QST_order'         => 1,
951
+							'QST_admin_only'    => 0,
952
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
953
+							'QST_wp_user'       => self::get_default_creator_id(),
954
+							'QST_deleted'       => 0,
955
+						);
956
+						break;
957
+					case 'lname':
958
+						$QST_values = array(
959
+							'QST_display_text'  => __('Last Name', 'event_espresso'),
960
+							'QST_admin_label'   => __('Last Name - System Question', 'event_espresso'),
961
+							'QST_system'        => 'lname',
962
+							'QST_type'          => 'TEXT',
963
+							'QST_required'      => 1,
964
+							'QST_required_text' => __('This field is required', 'event_espresso'),
965
+							'QST_order'         => 2,
966
+							'QST_admin_only'    => 0,
967
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
968
+							'QST_wp_user'       => self::get_default_creator_id(),
969
+							'QST_deleted'       => 0,
970
+						);
971
+						break;
972
+					case 'email':
973
+						$QST_values = array(
974
+							'QST_display_text'  => __('Email Address', 'event_espresso'),
975
+							'QST_admin_label'   => __('Email Address - System Question', 'event_espresso'),
976
+							'QST_system'        => 'email',
977
+							'QST_type'          => 'EMAIL',
978
+							'QST_required'      => 1,
979
+							'QST_required_text' => __('This field is required', 'event_espresso'),
980
+							'QST_order'         => 3,
981
+							'QST_admin_only'    => 0,
982
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
983
+							'QST_wp_user'       => self::get_default_creator_id(),
984
+							'QST_deleted'       => 0,
985
+						);
986
+						break;
987
+					case 'address':
988
+						$QST_values = array(
989
+							'QST_display_text'  => __('Address', 'event_espresso'),
990
+							'QST_admin_label'   => __('Address - System Question', 'event_espresso'),
991
+							'QST_system'        => 'address',
992
+							'QST_type'          => 'TEXT',
993
+							'QST_required'      => 0,
994
+							'QST_required_text' => __('This field is required', 'event_espresso'),
995
+							'QST_order'         => 4,
996
+							'QST_admin_only'    => 0,
997
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
998
+							'QST_wp_user'       => self::get_default_creator_id(),
999
+							'QST_deleted'       => 0,
1000
+						);
1001
+						break;
1002
+					case 'address2':
1003
+						$QST_values = array(
1004
+							'QST_display_text'  => __('Address2', 'event_espresso'),
1005
+							'QST_admin_label'   => __('Address2 - System Question', 'event_espresso'),
1006
+							'QST_system'        => 'address2',
1007
+							'QST_type'          => 'TEXT',
1008
+							'QST_required'      => 0,
1009
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1010
+							'QST_order'         => 5,
1011
+							'QST_admin_only'    => 0,
1012
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1013
+							'QST_wp_user'       => self::get_default_creator_id(),
1014
+							'QST_deleted'       => 0,
1015
+						);
1016
+						break;
1017
+					case 'city':
1018
+						$QST_values = array(
1019
+							'QST_display_text'  => __('City', 'event_espresso'),
1020
+							'QST_admin_label'   => __('City - System Question', 'event_espresso'),
1021
+							'QST_system'        => 'city',
1022
+							'QST_type'          => 'TEXT',
1023
+							'QST_required'      => 0,
1024
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1025
+							'QST_order'         => 6,
1026
+							'QST_admin_only'    => 0,
1027
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1028
+							'QST_wp_user'       => self::get_default_creator_id(),
1029
+							'QST_deleted'       => 0,
1030
+						);
1031
+						break;
1032
+					case 'country':
1033
+						$QST_values = array(
1034
+							'QST_display_text'  => __('Country', 'event_espresso'),
1035
+							'QST_admin_label'   => __('Country - System Question', 'event_espresso'),
1036
+							'QST_system'        => 'country',
1037
+							'QST_type'          => 'COUNTRY',
1038
+							'QST_required'      => 0,
1039
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1040
+							'QST_order'         => 7,
1041
+							'QST_admin_only'    => 0,
1042
+							'QST_wp_user'       => self::get_default_creator_id(),
1043
+							'QST_deleted'       => 0,
1044
+						);
1045
+						break;
1046
+					case 'state':
1047
+						$QST_values = array(
1048
+							'QST_display_text'  => __('State/Province', 'event_espresso'),
1049
+							'QST_admin_label'   => __('State/Province - System Question', 'event_espresso'),
1050
+							'QST_system'        => 'state',
1051
+							'QST_type'          => 'STATE',
1052
+							'QST_required'      => 0,
1053
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1054
+							'QST_order'         => 8,
1055
+							'QST_admin_only'    => 0,
1056
+							'QST_wp_user'       => self::get_default_creator_id(),
1057
+							'QST_deleted'       => 0,
1058
+						);
1059
+						break;
1060
+					case 'zip':
1061
+						$QST_values = array(
1062
+							'QST_display_text'  => __('Zip/Postal Code', 'event_espresso'),
1063
+							'QST_admin_label'   => __('Zip/Postal Code - System Question', 'event_espresso'),
1064
+							'QST_system'        => 'zip',
1065
+							'QST_type'          => 'TEXT',
1066
+							'QST_required'      => 0,
1067
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1068
+							'QST_order'         => 9,
1069
+							'QST_admin_only'    => 0,
1070
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1071
+							'QST_wp_user'       => self::get_default_creator_id(),
1072
+							'QST_deleted'       => 0,
1073
+						);
1074
+						break;
1075
+					case 'phone':
1076
+						$QST_values = array(
1077
+							'QST_display_text'  => __('Phone Number', 'event_espresso'),
1078
+							'QST_admin_label'   => __('Phone Number - System Question', 'event_espresso'),
1079
+							'QST_system'        => 'phone',
1080
+							'QST_type'          => 'TEXT',
1081
+							'QST_required'      => 0,
1082
+							'QST_required_text' => __('This field is required', 'event_espresso'),
1083
+							'QST_order'         => 10,
1084
+							'QST_admin_only'    => 0,
1085
+							'QST_max'           => EEM_Question::instance()->absolute_max_for_system_question($QST_system),
1086
+							'QST_wp_user'       => self::get_default_creator_id(),
1087
+							'QST_deleted'       => 0,
1088
+						);
1089
+						break;
1090
+				}
1091
+				if (! empty($QST_values)) {
1092
+					// insert system question
1093
+					$wpdb->insert(
1094
+						$table_name,
1095
+						$QST_values,
1096
+						array('%s', '%s', '%s', '%s', '%d', '%s', '%d', '%d', '%d', '%d')
1097
+					);
1098
+					$QST_ID = $wpdb->insert_id;
1099
+					// QUESTION GROUP QUESTIONS
1100
+					if (in_array($QST_system, array('fname', 'lname', 'email'))) {
1101
+						$system_question_we_want = EEM_Question_Group::system_personal;
1102
+					} else {
1103
+						$system_question_we_want = EEM_Question_Group::system_address;
1104
+					}
1105
+					if (isset($QSG_IDs[$system_question_we_want])) {
1106
+						$QSG_ID = $QSG_IDs[$system_question_we_want];
1107
+					} else {
1108
+						$id_col = EEM_Question_Group::instance()
1109
+													->get_col(array(array('QSG_system' => $system_question_we_want)));
1110
+						if (is_array($id_col)) {
1111
+							$QSG_ID = reset($id_col);
1112
+						} else {
1113
+							//ok so we didn't find it in the db either?? that's weird because we should have inserted it at the start of this method
1114
+							EE_Log::instance()->log(
1115
+								__FILE__,
1116
+								__FUNCTION__,
1117
+								sprintf(
1118
+									__(
1119
+										'Could not associate question %1$s to a question group because no system question
1120 1120
                                          group existed',
1121
-                                        'event_espresso'
1122
-                                    ),
1123
-                                    $QST_ID),
1124
-                                'error');
1125
-                            continue;
1126
-                        }
1127
-                    }
1128
-                    // add system questions to groups
1129
-                    $wpdb->insert(
1130
-                        \EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1131
-                        array(
1132
-                            'QSG_ID'    => $QSG_ID,
1133
-                            'QST_ID'    => $QST_ID,
1134
-                            'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1135
-                        ),
1136
-                        array('%d', '%d', '%d')
1137
-                    );
1138
-                }
1139
-            }
1140
-        }
1141
-    }
1142
-
1143
-
1144
-    /**
1145
-     * Makes sure the default payment method (Invoice) is active.
1146
-     * This used to be done automatically as part of constructing the old gateways config
1147
-     *
1148
-     * @throws \EE_Error
1149
-     */
1150
-    public static function insert_default_payment_methods()
1151
-    {
1152
-        if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1153
-            EE_Registry::instance()->load_lib('Payment_Method_Manager');
1154
-            EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1155
-        } else {
1156
-            EEM_Payment_Method::instance()->verify_button_urls();
1157
-        }
1158
-    }
1159
-
1160
-    /**
1161
-     * insert_default_status_codes
1162
-     *
1163
-     * @access public
1164
-     * @static
1165
-     * @return void
1166
-     */
1167
-    public static function insert_default_status_codes()
1168
-    {
1169
-
1170
-        global $wpdb;
1171
-
1172
-        if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1173
-
1174
-            $table_name = EEM_Status::instance()->table();
1175
-
1176
-            $SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1177
-            $wpdb->query($SQL);
1178
-
1179
-            $SQL = "INSERT INTO $table_name
1121
+										'event_espresso'
1122
+									),
1123
+									$QST_ID),
1124
+								'error');
1125
+							continue;
1126
+						}
1127
+					}
1128
+					// add system questions to groups
1129
+					$wpdb->insert(
1130
+						\EEH_Activation::getTableAnalysis()->ensureTableNameHasPrefix('esp_question_group_question'),
1131
+						array(
1132
+							'QSG_ID'    => $QSG_ID,
1133
+							'QST_ID'    => $QST_ID,
1134
+							'QGQ_order' => ($QSG_ID === 1) ? $order_for_group_1++ : $order_for_group_2++,
1135
+						),
1136
+						array('%d', '%d', '%d')
1137
+					);
1138
+				}
1139
+			}
1140
+		}
1141
+	}
1142
+
1143
+
1144
+	/**
1145
+	 * Makes sure the default payment method (Invoice) is active.
1146
+	 * This used to be done automatically as part of constructing the old gateways config
1147
+	 *
1148
+	 * @throws \EE_Error
1149
+	 */
1150
+	public static function insert_default_payment_methods()
1151
+	{
1152
+		if (! EEM_Payment_Method::instance()->count_active(EEM_Payment_Method::scope_cart)) {
1153
+			EE_Registry::instance()->load_lib('Payment_Method_Manager');
1154
+			EE_Payment_Method_Manager::instance()->activate_a_payment_method_of_type('Invoice');
1155
+		} else {
1156
+			EEM_Payment_Method::instance()->verify_button_urls();
1157
+		}
1158
+	}
1159
+
1160
+	/**
1161
+	 * insert_default_status_codes
1162
+	 *
1163
+	 * @access public
1164
+	 * @static
1165
+	 * @return void
1166
+	 */
1167
+	public static function insert_default_status_codes()
1168
+	{
1169
+
1170
+		global $wpdb;
1171
+
1172
+		if (\EEH_Activation::getTableAnalysis()->tableExists(EEM_Status::instance()->table())) {
1173
+
1174
+			$table_name = EEM_Status::instance()->table();
1175
+
1176
+			$SQL = "DELETE FROM $table_name WHERE STS_ID IN ( 'ACT', 'NAC', 'NOP', 'OPN', 'CLS', 'PND', 'ONG', 'SEC', 'DRF', 'DEL', 'DEN', 'EXP', 'RPP', 'RCN', 'RDC', 'RAP', 'RNA', 'RWL', 'TAB', 'TIN', 'TFL', 'TCM', 'TOP', 'PAP', 'PCN', 'PFL', 'PDC', 'EDR', 'ESN', 'PPN', 'RIC', 'MSN', 'MFL', 'MID', 'MRS', 'MIC', 'MDO', 'MEX' );";
1177
+			$wpdb->query($SQL);
1178
+
1179
+			$SQL = "INSERT INTO $table_name
1180 1180
 					(STS_ID, STS_code, STS_type, STS_can_edit, STS_desc, STS_open) VALUES
1181 1181
 					('ACT', 'ACTIVE', 'event', 0, NULL, 1),
1182 1182
 					('NAC', 'NOT_ACTIVE', 'event', 0, NULL, 0),
@@ -1216,521 +1216,521 @@  discard block
 block discarded – undo
1216 1216
 					('MID', 'IDLE', 'message', 0, NULL, 1),
1217 1217
 					('MRS', 'RESEND', 'message', 0, NULL, 1),
1218 1218
 					('MIC', 'INCOMPLETE', 'message', 0, NULL, 0);";
1219
-            $wpdb->query($SQL);
1220
-
1221
-        }
1222
-
1223
-    }
1224
-
1225
-
1226
-    /**
1227
-     * create_upload_directories
1228
-     * Creates folders in the uploads directory to facilitate addons and templates
1229
-     *
1230
-     * @access public
1231
-     * @static
1232
-     * @return boolean success of verifying upload directories exist
1233
-     */
1234
-    public static function create_upload_directories()
1235
-    {
1236
-        // Create the required folders
1237
-        $folders = array(
1238
-            EVENT_ESPRESSO_TEMPLATE_DIR,
1239
-            EVENT_ESPRESSO_GATEWAY_DIR,
1240
-            EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1241
-            EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1242
-            EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1243
-        );
1244
-        foreach ($folders as $folder) {
1245
-            try {
1246
-                EEH_File::ensure_folder_exists_and_is_writable($folder);
1247
-                @ chmod($folder, 0755);
1248
-            } catch (EE_Error $e) {
1249
-                EE_Error::add_error(
1250
-                    sprintf(
1251
-                        __('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1252
-                        $folder,
1253
-                        '<br />' . $e->getMessage()
1254
-                    ),
1255
-                    __FILE__, __FUNCTION__, __LINE__
1256
-                );
1257
-                //indicate we'll need to fix this later
1258
-                update_option(EEH_Activation::upload_directories_incomplete_option_name, true);
1259
-                return false;
1260
-            }
1261
-        }
1262
-        //just add the .htaccess file to the logs directory to begin with. Even if logging
1263
-        //is disabled, there might be activation errors recorded in there
1264
-        EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1265
-        //remember EE's folders are all good
1266
-        delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1267
-        return true;
1268
-    }
1269
-
1270
-    /**
1271
-     * Whether the upload directories need to be fixed or not.
1272
-     * If EE is installed but filesystem access isn't initially available,
1273
-     * we need to get the user's filesystem credentials and THEN create them,
1274
-     * so there might be period of time when EE is installed but its
1275
-     * upload directories aren't available. This indicates such a state
1276
-     *
1277
-     * @return boolean
1278
-     */
1279
-    public static function upload_directories_incomplete()
1280
-    {
1281
-        return get_option(EEH_Activation::upload_directories_incomplete_option_name, false);
1282
-    }
1283
-
1284
-
1285
-    /**
1286
-     * generate_default_message_templates
1287
-     *
1288
-     * @static
1289
-     * @throws EE_Error
1290
-     * @return bool     true means new templates were created.
1291
-     *                  false means no templates were created.
1292
-     *                  This is NOT an error flag. To check for errors you will want
1293
-     *                  to use either EE_Error or a try catch for an EE_Error exception.
1294
-     */
1295
-    public static function generate_default_message_templates()
1296
-    {
1297
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1298
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1299
-        /*
1219
+			$wpdb->query($SQL);
1220
+
1221
+		}
1222
+
1223
+	}
1224
+
1225
+
1226
+	/**
1227
+	 * create_upload_directories
1228
+	 * Creates folders in the uploads directory to facilitate addons and templates
1229
+	 *
1230
+	 * @access public
1231
+	 * @static
1232
+	 * @return boolean success of verifying upload directories exist
1233
+	 */
1234
+	public static function create_upload_directories()
1235
+	{
1236
+		// Create the required folders
1237
+		$folders = array(
1238
+			EVENT_ESPRESSO_TEMPLATE_DIR,
1239
+			EVENT_ESPRESSO_GATEWAY_DIR,
1240
+			EVENT_ESPRESSO_UPLOAD_DIR . 'logs/',
1241
+			EVENT_ESPRESSO_UPLOAD_DIR . 'css/',
1242
+			EVENT_ESPRESSO_UPLOAD_DIR . 'tickets/',
1243
+		);
1244
+		foreach ($folders as $folder) {
1245
+			try {
1246
+				EEH_File::ensure_folder_exists_and_is_writable($folder);
1247
+				@ chmod($folder, 0755);
1248
+			} catch (EE_Error $e) {
1249
+				EE_Error::add_error(
1250
+					sprintf(
1251
+						__('Could not create the folder at "%1$s" because: %2$s', 'event_espresso'),
1252
+						$folder,
1253
+						'<br />' . $e->getMessage()
1254
+					),
1255
+					__FILE__, __FUNCTION__, __LINE__
1256
+				);
1257
+				//indicate we'll need to fix this later
1258
+				update_option(EEH_Activation::upload_directories_incomplete_option_name, true);
1259
+				return false;
1260
+			}
1261
+		}
1262
+		//just add the .htaccess file to the logs directory to begin with. Even if logging
1263
+		//is disabled, there might be activation errors recorded in there
1264
+		EEH_File::add_htaccess_deny_from_all(EVENT_ESPRESSO_UPLOAD_DIR . 'logs/');
1265
+		//remember EE's folders are all good
1266
+		delete_option(EEH_Activation::upload_directories_incomplete_option_name);
1267
+		return true;
1268
+	}
1269
+
1270
+	/**
1271
+	 * Whether the upload directories need to be fixed or not.
1272
+	 * If EE is installed but filesystem access isn't initially available,
1273
+	 * we need to get the user's filesystem credentials and THEN create them,
1274
+	 * so there might be period of time when EE is installed but its
1275
+	 * upload directories aren't available. This indicates such a state
1276
+	 *
1277
+	 * @return boolean
1278
+	 */
1279
+	public static function upload_directories_incomplete()
1280
+	{
1281
+		return get_option(EEH_Activation::upload_directories_incomplete_option_name, false);
1282
+	}
1283
+
1284
+
1285
+	/**
1286
+	 * generate_default_message_templates
1287
+	 *
1288
+	 * @static
1289
+	 * @throws EE_Error
1290
+	 * @return bool     true means new templates were created.
1291
+	 *                  false means no templates were created.
1292
+	 *                  This is NOT an error flag. To check for errors you will want
1293
+	 *                  to use either EE_Error or a try catch for an EE_Error exception.
1294
+	 */
1295
+	public static function generate_default_message_templates()
1296
+	{
1297
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1298
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1299
+		/*
1300 1300
          * This first method is taking care of ensuring any default messengers
1301 1301
          * that should be made active and have templates generated are done.
1302 1302
          */
1303
-        $new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1304
-            $message_resource_manager
1305
-        );
1306
-        /**
1307
-         * This method is verifying there are no NEW default message types
1308
-         * for ACTIVE messengers that need activated (and corresponding templates setup).
1309
-         */
1310
-        $new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1311
-            $message_resource_manager
1312
-        );
1313
-        //after all is done, let's persist these changes to the db.
1314
-        $message_resource_manager->update_has_activated_messengers_option();
1315
-        $message_resource_manager->update_active_messengers_option();
1316
-        // will return true if either of these are true.  Otherwise will return false.
1317
-        return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1318
-    }
1319
-
1320
-
1321
-
1322
-    /**
1323
-     * @param \EE_Message_Resource_Manager $message_resource_manager
1324
-     * @return array|bool
1325
-     * @throws \EE_Error
1326
-     */
1327
-    protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1328
-        EE_Message_Resource_Manager $message_resource_manager
1329
-    ) {
1330
-        /** @type EE_messenger[] $active_messengers */
1331
-        $active_messengers = $message_resource_manager->active_messengers();
1332
-        $installed_message_types = $message_resource_manager->installed_message_types();
1333
-        $templates_created = false;
1334
-        foreach ($active_messengers as $active_messenger) {
1335
-            $default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1336
-            $default_message_type_names_to_activate = array();
1337
-            // looping through each default message type reported by the messenger
1338
-            // and setup the actual message types to activate.
1339
-            foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1340
-                // if already active or has already been activated before we skip
1341
-                // (otherwise we might reactivate something user's intentionally deactivated.)
1342
-                // we also skip if the message type is not installed.
1343
-                if (
1344
-                    $message_resource_manager->has_message_type_been_activated_for_messenger(
1345
-                        $default_message_type_name_for_messenger,
1346
-                        $active_messenger->name
1347
-                    )
1348
-                    || $message_resource_manager->is_message_type_active_for_messenger(
1349
-                        $active_messenger->name,
1350
-                        $default_message_type_name_for_messenger
1351
-                    )
1352
-                    || ! isset($installed_message_types[$default_message_type_name_for_messenger])
1353
-                ) {
1354
-                    continue;
1355
-                }
1356
-                $default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1357
-            }
1358
-            //let's activate!
1359
-            $message_resource_manager->ensure_message_types_are_active(
1360
-                $default_message_type_names_to_activate,
1361
-                $active_messenger->name,
1362
-                false
1363
-            );
1364
-            //activate the templates for these message types
1365
-            if ( ! empty($default_message_type_names_to_activate)) {
1366
-                $templates_created = EEH_MSG_Template::generate_new_templates(
1367
-                    $active_messenger->name,
1368
-                    $default_message_type_names_for_messenger,
1369
-                    '',
1370
-                    true
1371
-                );
1372
-            }
1373
-        }
1374
-        return $templates_created;
1375
-    }
1376
-
1377
-
1378
-
1379
-    /**
1380
-     * This will activate and generate default messengers and default message types for those messengers.
1381
-     *
1382
-     * @param EE_message_Resource_Manager $message_resource_manager
1383
-     * @return array|bool  True means there were default messengers and message type templates generated.
1384
-     *                     False means that there were no templates generated
1385
-     *                     (which could simply mean there are no default message types for a messenger).
1386
-     * @throws EE_Error
1387
-     */
1388
-    protected static function _activate_and_generate_default_messengers_and_message_templates(
1389
-        EE_Message_Resource_Manager $message_resource_manager
1390
-    ) {
1391
-        /** @type EE_messenger[] $messengers_to_generate */
1392
-        $messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1393
-        $installed_message_types = $message_resource_manager->installed_message_types();
1394
-        $templates_generated = false;
1395
-        foreach ($messengers_to_generate as $messenger_to_generate) {
1396
-            $default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1397
-            //verify the default message types match an installed message type.
1398
-            foreach ($default_message_type_names_for_messenger as $key => $name) {
1399
-                if (
1400
-                    ! isset($installed_message_types[$name])
1401
-                    || $message_resource_manager->has_message_type_been_activated_for_messenger(
1402
-                        $name,
1403
-                        $messenger_to_generate->name
1404
-                    )
1405
-                ) {
1406
-                    unset($default_message_type_names_for_messenger[$key]);
1407
-                }
1408
-            }
1409
-            // in previous iterations, the active_messengers option in the db
1410
-            // needed updated before calling create templates. however with the changes this may not be necessary.
1411
-            // This comment is left here just in case we discover that we _do_ need to update before
1412
-            // passing off to create templates (after the refactor is done).
1413
-            // @todo remove this comment when determined not necessary.
1414
-            $message_resource_manager->activate_messenger(
1415
-                $messenger_to_generate->name,
1416
-                $default_message_type_names_for_messenger,
1417
-                false
1418
-            );
1419
-            //create any templates needing created (or will reactivate templates already generated as necessary).
1420
-            if ( ! empty($default_message_type_names_for_messenger)) {
1421
-                $templates_generated = EEH_MSG_Template::generate_new_templates(
1422
-                    $messenger_to_generate->name,
1423
-                    $default_message_type_names_for_messenger,
1424
-                    '',
1425
-                    true
1426
-                );
1427
-            }
1428
-        }
1429
-        return $templates_generated;
1430
-    }
1431
-
1432
-
1433
-    /**
1434
-     * This returns the default messengers to generate templates for on activation of EE.
1435
-     * It considers:
1436
-     * - whether a messenger is already active in the db.
1437
-     * - whether a messenger has been made active at any time in the past.
1438
-     *
1439
-     * @static
1440
-     * @param  EE_Message_Resource_Manager $message_resource_manager
1441
-     * @return EE_messenger[]
1442
-     */
1443
-    protected static function _get_default_messengers_to_generate_on_activation(
1444
-        EE_Message_Resource_Manager $message_resource_manager
1445
-    ) {
1446
-        $active_messengers    = $message_resource_manager->active_messengers();
1447
-        $installed_messengers = $message_resource_manager->installed_messengers();
1448
-        $has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1449
-
1450
-        $messengers_to_generate = array();
1451
-        foreach ($installed_messengers as $installed_messenger) {
1452
-            //if installed messenger is a messenger that should be activated on install
1453
-            //and is not already active
1454
-            //and has never been activated
1455
-            if (
1456
-                ! $installed_messenger->activate_on_install
1457
-                || isset($active_messengers[$installed_messenger->name])
1458
-                || isset($has_activated[$installed_messenger->name])
1459
-            ) {
1460
-                continue;
1461
-            }
1462
-            $messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1463
-        }
1464
-        return $messengers_to_generate;
1465
-    }
1466
-
1467
-
1468
-    /**
1469
-     * This simply validates active message types to ensure they actually match installed
1470
-     * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1471
-     * rows are set inactive.
1472
-     * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1473
-     * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1474
-     * are still handled in here.
1475
-     *
1476
-     * @since 4.3.1
1477
-     * @return void
1478
-     */
1479
-    public static function validate_messages_system()
1480
-    {
1481
-        /** @type EE_Message_Resource_Manager $message_resource_manager */
1482
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1483
-        $message_resource_manager->validate_active_message_types_are_installed();
1484
-        do_action('AHEE__EEH_Activation__validate_messages_system');
1485
-    }
1486
-
1487
-
1488
-    /**
1489
-     * create_no_ticket_prices_array
1490
-     *
1491
-     * @access public
1492
-     * @static
1493
-     * @return void
1494
-     */
1495
-    public static function create_no_ticket_prices_array()
1496
-    {
1497
-        // this creates an array for tracking events that have no active ticket prices created
1498
-        // this allows us to warn admins of the situation so that it can be corrected
1499
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1500
-        if (! $espresso_no_ticket_prices) {
1501
-            add_option('ee_no_ticket_prices', array(), '', false);
1502
-        }
1503
-    }
1504
-
1505
-
1506
-    /**
1507
-     * plugin_deactivation
1508
-     *
1509
-     * @access public
1510
-     * @static
1511
-     * @return void
1512
-     */
1513
-    public static function plugin_deactivation()
1514
-    {
1515
-    }
1516
-
1517
-
1518
-    /**
1519
-     * Finds all our EE4 custom post types, and deletes them and their associated data
1520
-     * (like post meta or term relations)
1521
-     *
1522
-     * @global wpdb $wpdb
1523
-     * @throws \EE_Error
1524
-     */
1525
-    public static function delete_all_espresso_cpt_data()
1526
-    {
1527
-        global $wpdb;
1528
-        //get all the CPT post_types
1529
-        $ee_post_types = array();
1530
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1531
-            if (method_exists($model_name, 'instance')) {
1532
-                $model_obj = call_user_func(array($model_name, 'instance'));
1533
-                if ($model_obj instanceof EEM_CPT_Base) {
1534
-                    $ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1535
-                }
1536
-            }
1537
-        }
1538
-        //get all our CPTs
1539
-        $query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1540
-        $cpt_ids = $wpdb->get_col($query);
1541
-        //delete each post meta and term relations too
1542
-        foreach ($cpt_ids as $post_id) {
1543
-            wp_delete_post($post_id, true);
1544
-        }
1545
-    }
1546
-
1547
-    /**
1548
-     * Deletes all EE custom tables
1549
-     *
1550
-     * @return array
1551
-     */
1552
-    public static function drop_espresso_tables()
1553
-    {
1554
-        $tables = array();
1555
-        // load registry
1556
-        foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1557
-            if (method_exists($model_name, 'instance')) {
1558
-                $model_obj = call_user_func(array($model_name, 'instance'));
1559
-                if ($model_obj instanceof EEM_Base) {
1560
-                    foreach ($model_obj->get_tables() as $table) {
1561
-                        if (strpos($table->get_table_name(), 'esp_')
1562
-                            &&
1563
-                            (
1564
-                                is_main_site()//main site? nuke them all
1565
-                                || ! $table->is_global()//not main site,but not global either. nuke it
1566
-                            )
1567
-                        ) {
1568
-                            $tables[$table->get_table_name()] = $table->get_table_name();
1569
-                        }
1570
-                    }
1571
-                }
1572
-            }
1573
-        }
1574
-
1575
-        //there are some tables whose models were removed.
1576
-        //they should be removed when removing all EE core's data
1577
-        $tables_without_models = array(
1578
-            'esp_promotion',
1579
-            'esp_promotion_applied',
1580
-            'esp_promotion_object',
1581
-            'esp_promotion_rule',
1582
-            'esp_rule',
1583
-        );
1584
-        foreach ($tables_without_models as $table) {
1585
-            $tables[$table] = $table;
1586
-        }
1587
-        return \EEH_Activation::getTableManager()->dropTables($tables);
1588
-    }
1589
-
1590
-
1591
-
1592
-    /**
1593
-     * Drops all the tables mentioned in a single MYSQL query. Double-checks
1594
-     * each table name provided has a wpdb prefix attached, and that it exists.
1595
-     * Returns the list actually deleted
1596
-     *
1597
-     * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1598
-     * @global WPDB $wpdb
1599
-     * @param array $table_names
1600
-     * @return array of table names which we deleted
1601
-     */
1602
-    public static function drop_tables($table_names)
1603
-    {
1604
-        return \EEH_Activation::getTableManager()->dropTables($table_names);
1605
-    }
1606
-
1607
-
1608
-
1609
-    /**
1610
-     * plugin_uninstall
1611
-     *
1612
-     * @access public
1613
-     * @static
1614
-     * @param bool $remove_all
1615
-     * @return void
1616
-     */
1617
-    public static function delete_all_espresso_tables_and_data($remove_all = true)
1618
-    {
1619
-        global $wpdb;
1620
-        self::drop_espresso_tables();
1621
-        $wp_options_to_delete = array(
1622
-            'ee_no_ticket_prices'                => true,
1623
-            'ee_active_messengers'               => true,
1624
-            'ee_has_activated_messenger'         => true,
1625
-            'ee_flush_rewrite_rules'             => true,
1626
-            'ee_config'                          => false,
1627
-            'ee_data_migration_current_db_state' => true,
1628
-            'ee_data_migration_mapping_'         => false,
1629
-            'ee_data_migration_script_'          => false,
1630
-            'ee_data_migrations'                 => true,
1631
-            'ee_dms_map'                         => false,
1632
-            'ee_notices'                         => true,
1633
-            'lang_file_check_'                   => false,
1634
-            'ee_maintenance_mode'                => true,
1635
-            'ee_ueip_optin'                      => true,
1636
-            'ee_ueip_has_notified'               => true,
1637
-            'ee_plugin_activation_errors'        => true,
1638
-            'ee_id_mapping_from'                 => false,
1639
-            'espresso_persistent_admin_notices'  => true,
1640
-            'ee_encryption_key'                  => true,
1641
-            'pue_force_upgrade_'                 => false,
1642
-            'pue_json_error_'                    => false,
1643
-            'pue_install_key_'                   => false,
1644
-            'pue_verification_error_'            => false,
1645
-            'pu_dismissed_upgrade_'              => false,
1646
-            'external_updates-'                  => false,
1647
-            'ee_extra_data'                      => true,
1648
-            'ee_ssn_'                            => false,
1649
-            'ee_rss_'                            => false,
1650
-            'ee_rte_n_tx_'                       => false,
1651
-            'ee_pers_admin_notices'              => true,
1652
-            'ee_job_parameters_'                 => false,
1653
-            'ee_upload_directories_incomplete'   => true,
1654
-            'ee_verified_db_collations'          => true,
1655
-        );
1656
-        if (is_main_site()) {
1657
-            $wp_options_to_delete['ee_network_config'] = true;
1658
-        }
1659
-        $undeleted_options = array();
1660
-        foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1661
-            if ($no_wildcard) {
1662
-                if ( ! delete_option($option_name)) {
1663
-                    $undeleted_options[] = $option_name;
1664
-                }
1665
-            } else {
1666
-                $option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1667
-                foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1668
-                    if ( ! delete_option($option_name_from_wildcard)) {
1669
-                        $undeleted_options[] = $option_name_from_wildcard;
1670
-                    }
1671
-                }
1672
-            }
1673
-        }
1674
-        //also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1675
-        remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1676
-        if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1677
-            $db_update_sans_ee4 = array();
1678
-            foreach ($espresso_db_update as $version => $times_activated) {
1679
-                if ((string)$version[0] === '3') {//if its NON EE4
1680
-                    $db_update_sans_ee4[$version] = $times_activated;
1681
-                }
1682
-            }
1683
-            update_option('espresso_db_update', $db_update_sans_ee4);
1684
-        }
1685
-        $errors = '';
1686
-        if ( ! empty($undeleted_options)) {
1687
-            $errors .= sprintf(
1688
-                __('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1689
-                '<br/>',
1690
-                implode(',<br/>', $undeleted_options)
1691
-            );
1692
-        }
1693
-        if ( ! empty($errors)) {
1694
-            EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1695
-        }
1696
-    }
1697
-
1698
-    /**
1699
-     * Gets the mysql error code from the last used query by wpdb
1700
-     *
1701
-     * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1702
-     */
1703
-    public static function last_wpdb_error_code()
1704
-    {
1705
-        global $wpdb;
1706
-        if ($wpdb->use_mysqli) {
1707
-            return mysqli_errno($wpdb->dbh);
1708
-        } else {
1709
-            return mysql_errno($wpdb->dbh);
1710
-        }
1711
-    }
1712
-
1713
-    /**
1714
-     * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1715
-     *
1716
-     * @global wpdb  $wpdb
1717
-     * @deprecated instead use TableAnalysis::tableExists()
1718
-     * @param string $table_name with or without $wpdb->prefix
1719
-     * @return boolean
1720
-     */
1721
-    public static function table_exists($table_name)
1722
-    {
1723
-        return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1724
-    }
1725
-
1726
-    /**
1727
-     * Resets the cache on EEH_Activation
1728
-     */
1729
-    public static function reset()
1730
-    {
1731
-        self::$_default_creator_id                             = null;
1732
-        self::$_initialized_db_content_already_in_this_request = false;
1733
-    }
1303
+		$new_templates_created_for_messenger = self::_activate_and_generate_default_messengers_and_message_templates(
1304
+			$message_resource_manager
1305
+		);
1306
+		/**
1307
+		 * This method is verifying there are no NEW default message types
1308
+		 * for ACTIVE messengers that need activated (and corresponding templates setup).
1309
+		 */
1310
+		$new_templates_created_for_message_type = self::_activate_new_message_types_for_active_messengers_and_generate_default_templates(
1311
+			$message_resource_manager
1312
+		);
1313
+		//after all is done, let's persist these changes to the db.
1314
+		$message_resource_manager->update_has_activated_messengers_option();
1315
+		$message_resource_manager->update_active_messengers_option();
1316
+		// will return true if either of these are true.  Otherwise will return false.
1317
+		return $new_templates_created_for_message_type || $new_templates_created_for_messenger;
1318
+	}
1319
+
1320
+
1321
+
1322
+	/**
1323
+	 * @param \EE_Message_Resource_Manager $message_resource_manager
1324
+	 * @return array|bool
1325
+	 * @throws \EE_Error
1326
+	 */
1327
+	protected static function _activate_new_message_types_for_active_messengers_and_generate_default_templates(
1328
+		EE_Message_Resource_Manager $message_resource_manager
1329
+	) {
1330
+		/** @type EE_messenger[] $active_messengers */
1331
+		$active_messengers = $message_resource_manager->active_messengers();
1332
+		$installed_message_types = $message_resource_manager->installed_message_types();
1333
+		$templates_created = false;
1334
+		foreach ($active_messengers as $active_messenger) {
1335
+			$default_message_type_names_for_messenger = $active_messenger->get_default_message_types();
1336
+			$default_message_type_names_to_activate = array();
1337
+			// looping through each default message type reported by the messenger
1338
+			// and setup the actual message types to activate.
1339
+			foreach ($default_message_type_names_for_messenger as $default_message_type_name_for_messenger) {
1340
+				// if already active or has already been activated before we skip
1341
+				// (otherwise we might reactivate something user's intentionally deactivated.)
1342
+				// we also skip if the message type is not installed.
1343
+				if (
1344
+					$message_resource_manager->has_message_type_been_activated_for_messenger(
1345
+						$default_message_type_name_for_messenger,
1346
+						$active_messenger->name
1347
+					)
1348
+					|| $message_resource_manager->is_message_type_active_for_messenger(
1349
+						$active_messenger->name,
1350
+						$default_message_type_name_for_messenger
1351
+					)
1352
+					|| ! isset($installed_message_types[$default_message_type_name_for_messenger])
1353
+				) {
1354
+					continue;
1355
+				}
1356
+				$default_message_type_names_to_activate[] = $default_message_type_name_for_messenger;
1357
+			}
1358
+			//let's activate!
1359
+			$message_resource_manager->ensure_message_types_are_active(
1360
+				$default_message_type_names_to_activate,
1361
+				$active_messenger->name,
1362
+				false
1363
+			);
1364
+			//activate the templates for these message types
1365
+			if ( ! empty($default_message_type_names_to_activate)) {
1366
+				$templates_created = EEH_MSG_Template::generate_new_templates(
1367
+					$active_messenger->name,
1368
+					$default_message_type_names_for_messenger,
1369
+					'',
1370
+					true
1371
+				);
1372
+			}
1373
+		}
1374
+		return $templates_created;
1375
+	}
1376
+
1377
+
1378
+
1379
+	/**
1380
+	 * This will activate and generate default messengers and default message types for those messengers.
1381
+	 *
1382
+	 * @param EE_message_Resource_Manager $message_resource_manager
1383
+	 * @return array|bool  True means there were default messengers and message type templates generated.
1384
+	 *                     False means that there were no templates generated
1385
+	 *                     (which could simply mean there are no default message types for a messenger).
1386
+	 * @throws EE_Error
1387
+	 */
1388
+	protected static function _activate_and_generate_default_messengers_and_message_templates(
1389
+		EE_Message_Resource_Manager $message_resource_manager
1390
+	) {
1391
+		/** @type EE_messenger[] $messengers_to_generate */
1392
+		$messengers_to_generate = self::_get_default_messengers_to_generate_on_activation($message_resource_manager);
1393
+		$installed_message_types = $message_resource_manager->installed_message_types();
1394
+		$templates_generated = false;
1395
+		foreach ($messengers_to_generate as $messenger_to_generate) {
1396
+			$default_message_type_names_for_messenger = $messenger_to_generate->get_default_message_types();
1397
+			//verify the default message types match an installed message type.
1398
+			foreach ($default_message_type_names_for_messenger as $key => $name) {
1399
+				if (
1400
+					! isset($installed_message_types[$name])
1401
+					|| $message_resource_manager->has_message_type_been_activated_for_messenger(
1402
+						$name,
1403
+						$messenger_to_generate->name
1404
+					)
1405
+				) {
1406
+					unset($default_message_type_names_for_messenger[$key]);
1407
+				}
1408
+			}
1409
+			// in previous iterations, the active_messengers option in the db
1410
+			// needed updated before calling create templates. however with the changes this may not be necessary.
1411
+			// This comment is left here just in case we discover that we _do_ need to update before
1412
+			// passing off to create templates (after the refactor is done).
1413
+			// @todo remove this comment when determined not necessary.
1414
+			$message_resource_manager->activate_messenger(
1415
+				$messenger_to_generate->name,
1416
+				$default_message_type_names_for_messenger,
1417
+				false
1418
+			);
1419
+			//create any templates needing created (or will reactivate templates already generated as necessary).
1420
+			if ( ! empty($default_message_type_names_for_messenger)) {
1421
+				$templates_generated = EEH_MSG_Template::generate_new_templates(
1422
+					$messenger_to_generate->name,
1423
+					$default_message_type_names_for_messenger,
1424
+					'',
1425
+					true
1426
+				);
1427
+			}
1428
+		}
1429
+		return $templates_generated;
1430
+	}
1431
+
1432
+
1433
+	/**
1434
+	 * This returns the default messengers to generate templates for on activation of EE.
1435
+	 * It considers:
1436
+	 * - whether a messenger is already active in the db.
1437
+	 * - whether a messenger has been made active at any time in the past.
1438
+	 *
1439
+	 * @static
1440
+	 * @param  EE_Message_Resource_Manager $message_resource_manager
1441
+	 * @return EE_messenger[]
1442
+	 */
1443
+	protected static function _get_default_messengers_to_generate_on_activation(
1444
+		EE_Message_Resource_Manager $message_resource_manager
1445
+	) {
1446
+		$active_messengers    = $message_resource_manager->active_messengers();
1447
+		$installed_messengers = $message_resource_manager->installed_messengers();
1448
+		$has_activated        = $message_resource_manager->get_has_activated_messengers_option();
1449
+
1450
+		$messengers_to_generate = array();
1451
+		foreach ($installed_messengers as $installed_messenger) {
1452
+			//if installed messenger is a messenger that should be activated on install
1453
+			//and is not already active
1454
+			//and has never been activated
1455
+			if (
1456
+				! $installed_messenger->activate_on_install
1457
+				|| isset($active_messengers[$installed_messenger->name])
1458
+				|| isset($has_activated[$installed_messenger->name])
1459
+			) {
1460
+				continue;
1461
+			}
1462
+			$messengers_to_generate[$installed_messenger->name] = $installed_messenger;
1463
+		}
1464
+		return $messengers_to_generate;
1465
+	}
1466
+
1467
+
1468
+	/**
1469
+	 * This simply validates active message types to ensure they actually match installed
1470
+	 * message types.  If there's a mismatch then we deactivate the message type and ensure all related db
1471
+	 * rows are set inactive.
1472
+	 * Note: Messengers are no longer validated here as of 4.9.0 because they get validated automatically whenever
1473
+	 * EE_Messenger_Resource_Manager is constructed.  Message Types are a bit more resource heavy for validation so they
1474
+	 * are still handled in here.
1475
+	 *
1476
+	 * @since 4.3.1
1477
+	 * @return void
1478
+	 */
1479
+	public static function validate_messages_system()
1480
+	{
1481
+		/** @type EE_Message_Resource_Manager $message_resource_manager */
1482
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1483
+		$message_resource_manager->validate_active_message_types_are_installed();
1484
+		do_action('AHEE__EEH_Activation__validate_messages_system');
1485
+	}
1486
+
1487
+
1488
+	/**
1489
+	 * create_no_ticket_prices_array
1490
+	 *
1491
+	 * @access public
1492
+	 * @static
1493
+	 * @return void
1494
+	 */
1495
+	public static function create_no_ticket_prices_array()
1496
+	{
1497
+		// this creates an array for tracking events that have no active ticket prices created
1498
+		// this allows us to warn admins of the situation so that it can be corrected
1499
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', false);
1500
+		if (! $espresso_no_ticket_prices) {
1501
+			add_option('ee_no_ticket_prices', array(), '', false);
1502
+		}
1503
+	}
1504
+
1505
+
1506
+	/**
1507
+	 * plugin_deactivation
1508
+	 *
1509
+	 * @access public
1510
+	 * @static
1511
+	 * @return void
1512
+	 */
1513
+	public static function plugin_deactivation()
1514
+	{
1515
+	}
1516
+
1517
+
1518
+	/**
1519
+	 * Finds all our EE4 custom post types, and deletes them and their associated data
1520
+	 * (like post meta or term relations)
1521
+	 *
1522
+	 * @global wpdb $wpdb
1523
+	 * @throws \EE_Error
1524
+	 */
1525
+	public static function delete_all_espresso_cpt_data()
1526
+	{
1527
+		global $wpdb;
1528
+		//get all the CPT post_types
1529
+		$ee_post_types = array();
1530
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1531
+			if (method_exists($model_name, 'instance')) {
1532
+				$model_obj = call_user_func(array($model_name, 'instance'));
1533
+				if ($model_obj instanceof EEM_CPT_Base) {
1534
+					$ee_post_types[] = $wpdb->prepare("%s", $model_obj->post_type());
1535
+				}
1536
+			}
1537
+		}
1538
+		//get all our CPTs
1539
+		$query   = "SELECT ID FROM {$wpdb->posts} WHERE post_type IN (" . implode(",", $ee_post_types) . ")";
1540
+		$cpt_ids = $wpdb->get_col($query);
1541
+		//delete each post meta and term relations too
1542
+		foreach ($cpt_ids as $post_id) {
1543
+			wp_delete_post($post_id, true);
1544
+		}
1545
+	}
1546
+
1547
+	/**
1548
+	 * Deletes all EE custom tables
1549
+	 *
1550
+	 * @return array
1551
+	 */
1552
+	public static function drop_espresso_tables()
1553
+	{
1554
+		$tables = array();
1555
+		// load registry
1556
+		foreach (EE_Registry::instance()->non_abstract_db_models as $model_name) {
1557
+			if (method_exists($model_name, 'instance')) {
1558
+				$model_obj = call_user_func(array($model_name, 'instance'));
1559
+				if ($model_obj instanceof EEM_Base) {
1560
+					foreach ($model_obj->get_tables() as $table) {
1561
+						if (strpos($table->get_table_name(), 'esp_')
1562
+							&&
1563
+							(
1564
+								is_main_site()//main site? nuke them all
1565
+								|| ! $table->is_global()//not main site,but not global either. nuke it
1566
+							)
1567
+						) {
1568
+							$tables[$table->get_table_name()] = $table->get_table_name();
1569
+						}
1570
+					}
1571
+				}
1572
+			}
1573
+		}
1574
+
1575
+		//there are some tables whose models were removed.
1576
+		//they should be removed when removing all EE core's data
1577
+		$tables_without_models = array(
1578
+			'esp_promotion',
1579
+			'esp_promotion_applied',
1580
+			'esp_promotion_object',
1581
+			'esp_promotion_rule',
1582
+			'esp_rule',
1583
+		);
1584
+		foreach ($tables_without_models as $table) {
1585
+			$tables[$table] = $table;
1586
+		}
1587
+		return \EEH_Activation::getTableManager()->dropTables($tables);
1588
+	}
1589
+
1590
+
1591
+
1592
+	/**
1593
+	 * Drops all the tables mentioned in a single MYSQL query. Double-checks
1594
+	 * each table name provided has a wpdb prefix attached, and that it exists.
1595
+	 * Returns the list actually deleted
1596
+	 *
1597
+	 * @deprecated in 4.9.13. Instead use TableManager::dropTables()
1598
+	 * @global WPDB $wpdb
1599
+	 * @param array $table_names
1600
+	 * @return array of table names which we deleted
1601
+	 */
1602
+	public static function drop_tables($table_names)
1603
+	{
1604
+		return \EEH_Activation::getTableManager()->dropTables($table_names);
1605
+	}
1606
+
1607
+
1608
+
1609
+	/**
1610
+	 * plugin_uninstall
1611
+	 *
1612
+	 * @access public
1613
+	 * @static
1614
+	 * @param bool $remove_all
1615
+	 * @return void
1616
+	 */
1617
+	public static function delete_all_espresso_tables_and_data($remove_all = true)
1618
+	{
1619
+		global $wpdb;
1620
+		self::drop_espresso_tables();
1621
+		$wp_options_to_delete = array(
1622
+			'ee_no_ticket_prices'                => true,
1623
+			'ee_active_messengers'               => true,
1624
+			'ee_has_activated_messenger'         => true,
1625
+			'ee_flush_rewrite_rules'             => true,
1626
+			'ee_config'                          => false,
1627
+			'ee_data_migration_current_db_state' => true,
1628
+			'ee_data_migration_mapping_'         => false,
1629
+			'ee_data_migration_script_'          => false,
1630
+			'ee_data_migrations'                 => true,
1631
+			'ee_dms_map'                         => false,
1632
+			'ee_notices'                         => true,
1633
+			'lang_file_check_'                   => false,
1634
+			'ee_maintenance_mode'                => true,
1635
+			'ee_ueip_optin'                      => true,
1636
+			'ee_ueip_has_notified'               => true,
1637
+			'ee_plugin_activation_errors'        => true,
1638
+			'ee_id_mapping_from'                 => false,
1639
+			'espresso_persistent_admin_notices'  => true,
1640
+			'ee_encryption_key'                  => true,
1641
+			'pue_force_upgrade_'                 => false,
1642
+			'pue_json_error_'                    => false,
1643
+			'pue_install_key_'                   => false,
1644
+			'pue_verification_error_'            => false,
1645
+			'pu_dismissed_upgrade_'              => false,
1646
+			'external_updates-'                  => false,
1647
+			'ee_extra_data'                      => true,
1648
+			'ee_ssn_'                            => false,
1649
+			'ee_rss_'                            => false,
1650
+			'ee_rte_n_tx_'                       => false,
1651
+			'ee_pers_admin_notices'              => true,
1652
+			'ee_job_parameters_'                 => false,
1653
+			'ee_upload_directories_incomplete'   => true,
1654
+			'ee_verified_db_collations'          => true,
1655
+		);
1656
+		if (is_main_site()) {
1657
+			$wp_options_to_delete['ee_network_config'] = true;
1658
+		}
1659
+		$undeleted_options = array();
1660
+		foreach ($wp_options_to_delete as $option_name => $no_wildcard) {
1661
+			if ($no_wildcard) {
1662
+				if ( ! delete_option($option_name)) {
1663
+					$undeleted_options[] = $option_name;
1664
+				}
1665
+			} else {
1666
+				$option_names_to_delete_from_wildcard = $wpdb->get_col("SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%$option_name%'");
1667
+				foreach ($option_names_to_delete_from_wildcard as $option_name_from_wildcard) {
1668
+					if ( ! delete_option($option_name_from_wildcard)) {
1669
+						$undeleted_options[] = $option_name_from_wildcard;
1670
+					}
1671
+				}
1672
+			}
1673
+		}
1674
+		//also, let's make sure the "ee_config_option_names" wp option stays out by removing the action that adds it
1675
+		remove_action('shutdown', array(EE_Config::instance(), 'shutdown'), 10);
1676
+		if ($remove_all && $espresso_db_update = get_option('espresso_db_update')) {
1677
+			$db_update_sans_ee4 = array();
1678
+			foreach ($espresso_db_update as $version => $times_activated) {
1679
+				if ((string)$version[0] === '3') {//if its NON EE4
1680
+					$db_update_sans_ee4[$version] = $times_activated;
1681
+				}
1682
+			}
1683
+			update_option('espresso_db_update', $db_update_sans_ee4);
1684
+		}
1685
+		$errors = '';
1686
+		if ( ! empty($undeleted_options)) {
1687
+			$errors .= sprintf(
1688
+				__('The following wp-options could not be deleted: %s%s', 'event_espresso'),
1689
+				'<br/>',
1690
+				implode(',<br/>', $undeleted_options)
1691
+			);
1692
+		}
1693
+		if ( ! empty($errors)) {
1694
+			EE_Error::add_attention($errors, __FILE__, __FUNCTION__, __LINE__);
1695
+		}
1696
+	}
1697
+
1698
+	/**
1699
+	 * Gets the mysql error code from the last used query by wpdb
1700
+	 *
1701
+	 * @return int mysql error code, see https://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html
1702
+	 */
1703
+	public static function last_wpdb_error_code()
1704
+	{
1705
+		global $wpdb;
1706
+		if ($wpdb->use_mysqli) {
1707
+			return mysqli_errno($wpdb->dbh);
1708
+		} else {
1709
+			return mysql_errno($wpdb->dbh);
1710
+		}
1711
+	}
1712
+
1713
+	/**
1714
+	 * Checks that the database table exists. Also works on temporary tables (for unit tests mostly).
1715
+	 *
1716
+	 * @global wpdb  $wpdb
1717
+	 * @deprecated instead use TableAnalysis::tableExists()
1718
+	 * @param string $table_name with or without $wpdb->prefix
1719
+	 * @return boolean
1720
+	 */
1721
+	public static function table_exists($table_name)
1722
+	{
1723
+		return \EEH_Activation::getTableAnalysis()->tableExists($table_name);
1724
+	}
1725
+
1726
+	/**
1727
+	 * Resets the cache on EEH_Activation
1728
+	 */
1729
+	public static function reset()
1730
+	{
1731
+		self::$_default_creator_id                             = null;
1732
+		self::$_initialized_db_content_already_in_this_request = false;
1733
+	}
1734 1734
 }
1735 1735
 // End of file EEH_Activation.helper.php
1736 1736
 // Location: /helpers/EEH_Activation.core.php
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 1 patch
Indentation   +3299 added lines, -3299 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php use EventEspresso\core\interfaces\InterminableInterface;
2 2
 
3 3
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 /**
7 7
  * Event Espresso
@@ -30,2114 +30,2114 @@  discard block
 block discarded – undo
30 30
 {
31 31
 
32 32
 
33
-    //set in _init_page_props()
34
-    public $page_slug;
33
+	//set in _init_page_props()
34
+	public $page_slug;
35 35
 
36
-    public $page_label;
36
+	public $page_label;
37 37
 
38
-    public $page_folder;
38
+	public $page_folder;
39 39
 
40
-    //set in define_page_props()
41
-    protected $_admin_base_url;
40
+	//set in define_page_props()
41
+	protected $_admin_base_url;
42 42
 
43
-    protected $_admin_base_path;
43
+	protected $_admin_base_path;
44 44
 
45
-    protected $_admin_page_title;
45
+	protected $_admin_page_title;
46 46
 
47
-    protected $_labels;
47
+	protected $_labels;
48 48
 
49 49
 
50
-    //set early within EE_Admin_Init
51
-    protected $_wp_page_slug;
50
+	//set early within EE_Admin_Init
51
+	protected $_wp_page_slug;
52 52
 
53
-    //navtabs
54
-    protected $_nav_tabs;
53
+	//navtabs
54
+	protected $_nav_tabs;
55 55
 
56
-    protected $_default_nav_tab_name;
56
+	protected $_default_nav_tab_name;
57 57
 
58
-    //helptourstops
59
-    protected $_help_tour = array();
58
+	//helptourstops
59
+	protected $_help_tour = array();
60 60
 
61 61
 
62
-    //template variables (used by templates)
63
-    protected $_template_path;
62
+	//template variables (used by templates)
63
+	protected $_template_path;
64 64
 
65
-    protected $_column_template_path;
65
+	protected $_column_template_path;
66 66
 
67
-    /**
68
-     * @var array $_template_args
69
-     */
70
-    protected $_template_args = array();
67
+	/**
68
+	 * @var array $_template_args
69
+	 */
70
+	protected $_template_args = array();
71 71
 
72
-    /**
73
-     * this will hold the list table object for a given view.
74
-     *
75
-     * @var EE_Admin_List_Table $_list_table_object
76
-     */
77
-    protected $_list_table_object;
72
+	/**
73
+	 * this will hold the list table object for a given view.
74
+	 *
75
+	 * @var EE_Admin_List_Table $_list_table_object
76
+	 */
77
+	protected $_list_table_object;
78 78
 
79
-    //bools
80
-    protected $_is_UI_request = null; //this starts at null so we can have no header routes progress through two states.
79
+	//bools
80
+	protected $_is_UI_request = null; //this starts at null so we can have no header routes progress through two states.
81 81
 
82
-    protected $_routing;
82
+	protected $_routing;
83 83
 
84
-    //list table args
85
-    protected $_view;
84
+	//list table args
85
+	protected $_view;
86 86
 
87
-    protected $_views;
87
+	protected $_views;
88 88
 
89 89
 
90
-    //action => method pairs used for routing incoming requests
91
-    protected $_page_routes;
90
+	//action => method pairs used for routing incoming requests
91
+	protected $_page_routes;
92 92
 
93
-    protected $_page_config;
93
+	protected $_page_config;
94 94
 
95
-    //the current page route and route config
96
-    protected $_route;
95
+	//the current page route and route config
96
+	protected $_route;
97 97
 
98
-    protected $_route_config;
98
+	protected $_route_config;
99 99
 
100
-    /**
101
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
102
-     * actions.
103
-     *
104
-     * @since 4.6.x
105
-     * @var array.
106
-     */
107
-    protected $_default_route_query_args;
100
+	/**
101
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
102
+	 * actions.
103
+	 *
104
+	 * @since 4.6.x
105
+	 * @var array.
106
+	 */
107
+	protected $_default_route_query_args;
108 108
 
109
-    //set via request page and action args.
110
-    protected $_current_page;
109
+	//set via request page and action args.
110
+	protected $_current_page;
111 111
 
112
-    protected $_current_view;
112
+	protected $_current_view;
113 113
 
114
-    protected $_current_page_view_url;
114
+	protected $_current_page_view_url;
115 115
 
116
-    //sanitized request action (and nonce)
117
-    /**
118
-     * @var string $_req_action
119
-     */
120
-    protected $_req_action;
116
+	//sanitized request action (and nonce)
117
+	/**
118
+	 * @var string $_req_action
119
+	 */
120
+	protected $_req_action;
121 121
 
122
-    /**
123
-     * @var string $_req_nonce
124
-     */
125
-    protected $_req_nonce;
122
+	/**
123
+	 * @var string $_req_nonce
124
+	 */
125
+	protected $_req_nonce;
126 126
 
127
-    //search related
128
-    protected $_search_btn_label;
127
+	//search related
128
+	protected $_search_btn_label;
129 129
 
130
-    protected $_search_box_callback;
130
+	protected $_search_box_callback;
131 131
 
132
-    /**
133
-     * WP Current Screen object
134
-     *
135
-     * @var WP_Screen
136
-     */
137
-    protected $_current_screen;
132
+	/**
133
+	 * WP Current Screen object
134
+	 *
135
+	 * @var WP_Screen
136
+	 */
137
+	protected $_current_screen;
138 138
 
139
-    //for holding EE_Admin_Hooks object when needed (set via set_hook_object())
140
-    protected $_hook_obj;
139
+	//for holding EE_Admin_Hooks object when needed (set via set_hook_object())
140
+	protected $_hook_obj;
141 141
 
142
-    //for holding incoming request data
143
-    protected $_req_data;
142
+	//for holding incoming request data
143
+	protected $_req_data;
144 144
 
145
-    // yes / no array for admin form fields
146
-    protected $_yes_no_values = array();
147
-
148
-    //some default things shared by all child classes
149
-    protected $_default_espresso_metaboxes;
150
-
151
-    /**
152
-     *    EE_Registry Object
153
-     *
154
-     * @var    EE_Registry
155
-     * @access    protected
156
-     */
157
-    protected $EE = null;
158
-
159
-
160
-
161
-    /**
162
-     * This is just a property that flags whether the given route is a caffeinated route or not.
163
-     *
164
-     * @var boolean
165
-     */
166
-    protected $_is_caf = false;
167
-
168
-
169
-
170
-    /**
171
-     * @Constructor
172
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
173
-     * @access public
174
-     */
175
-    public function __construct($routing = true)
176
-    {
177
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
178
-            $this->_is_caf = true;
179
-        }
180
-        $this->_yes_no_values = array(
181
-                array('id' => true, 'text' => __('Yes', 'event_espresso')),
182
-                array('id' => false, 'text' => __('No', 'event_espresso')),
183
-        );
184
-        //set the _req_data property.
185
-        $this->_req_data = array_merge($_GET, $_POST);
186
-        //routing enabled?
187
-        $this->_routing = $routing;
188
-        //set initial page props (child method)
189
-        $this->_init_page_props();
190
-        //set global defaults
191
-        $this->_set_defaults();
192
-        //set early because incoming requests could be ajax related and we need to register those hooks.
193
-        $this->_global_ajax_hooks();
194
-        $this->_ajax_hooks();
195
-        //other_page_hooks have to be early too.
196
-        $this->_do_other_page_hooks();
197
-        //This just allows us to have extending classes do something specific
198
-        // before the parent constructor runs _page_setup().
199
-        if (method_exists($this, '_before_page_setup')) {
200
-            $this->_before_page_setup();
201
-        }
202
-        //set up page dependencies
203
-        $this->_page_setup();
204
-    }
205
-
206
-
207
-
208
-    /**
209
-     * _init_page_props
210
-     * Child classes use to set at least the following properties:
211
-     * $page_slug.
212
-     * $page_label.
213
-     *
214
-     * @abstract
215
-     * @access protected
216
-     * @return void
217
-     */
218
-    abstract protected function _init_page_props();
219
-
220
-
221
-
222
-    /**
223
-     * _ajax_hooks
224
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
225
-     * Note: within the ajax callback methods.
226
-     *
227
-     * @abstract
228
-     * @access protected
229
-     * @return void
230
-     */
231
-    abstract protected function _ajax_hooks();
232
-
233
-
234
-
235
-    /**
236
-     * _define_page_props
237
-     * child classes define page properties in here.  Must include at least:
238
-     * $_admin_base_url = base_url for all admin pages
239
-     * $_admin_page_title = default admin_page_title for admin pages
240
-     * $_labels = array of default labels for various automatically generated elements:
241
-     *    array(
242
-     *        'buttons' => array(
243
-     *            'add' => __('label for add new button'),
244
-     *            'edit' => __('label for edit button'),
245
-     *            'delete' => __('label for delete button')
246
-     *            )
247
-     *        )
248
-     *
249
-     * @abstract
250
-     * @access protected
251
-     * @return void
252
-     */
253
-    abstract protected function _define_page_props();
254
-
255
-
256
-
257
-    /**
258
-     * _set_page_routes
259
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also have a 'default'
260
-     * route. Here's the format
261
-     * $this->_page_routes = array(
262
-     *        'default' => array(
263
-     *            'func' => '_default_method_handling_route',
264
-     *            'args' => array('array','of','args'),
265
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e. ajax request, backend processing)
266
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a headers route after.  The string you enter here should match the defined route reference for a headers sent route.
267
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access this route.
268
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability checks).
269
-     *        ),
270
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a handling method.
271
-     *        )
272
-     * )
273
-     *
274
-     * @abstract
275
-     * @access protected
276
-     * @return void
277
-     */
278
-    abstract protected function _set_page_routes();
279
-
280
-
281
-
282
-    /**
283
-     * _set_page_config
284
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the array corresponds to the page_route for the loaded page.
285
-     * Format:
286
-     * $this->_page_config = array(
287
-     *        'default' => array(
288
-     *            'labels' => array(
289
-     *                'buttons' => array(
290
-     *                    'add' => __('label for adding item'),
291
-     *                    'edit' => __('label for editing item'),
292
-     *                    'delete' => __('label for deleting item')
293
-     *                ),
294
-     *                'publishbox' => __('Localized Title for Publish metabox', 'event_espresso')
295
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the page. If this isn't present then the defaults will be used as set for the $this->_labels in _define_page_props() method
296
-     *            'nav' => array(
297
-     *                'label' => __('Label for Tab', 'event_espresso').
298
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
299
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
300
-     *                'order' => 10, //required to indicate tab position.
301
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is displayed then add this parameter.
302
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
303
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load metaboxes set for eventespresso admin pages.
304
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added later.  We just use
305
-     *            this flag to make sure the necessary js gets enqueued on page load.
306
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
307
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The array indicates the max number of columns (4) and the default number of columns on page load (2).  There is an option
308
-     *            in the "screen_options" dropdown that is setup so users can pick what columns they want to display.
309
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
310
-     *                'tab_id' => array(
311
-     *                    'title' => 'tab_title',
312
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting help tab content.  The fallback if it isn't present is to try a the callback.  Filename should match a file in the admin
313
-     *                    folder's "help_tabs" dir (ie.. events/help_tabs/name_of_file_containing_content.help_tab.php)
314
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will attempt to use the callback which should match the name of a method in the class
315
-     *                    ),
316
-     *                'tab2_id' => array(
317
-     *                    'title' => 'tab2 title',
318
-     *                    'filename' => 'file_name_2'
319
-     *                    'callback' => 'callback_method_for_content',
320
-     *                 ),
321
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the help tab area on an admin page. @link http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
322
-     *            'help_tour' => array(
323
-     *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located in a folder for this admin page named "help_tours", a file name matching the key given here
324
-     *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
325
-     *            ),
326
-     *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is true if it isn't present).  To remove the requirement for a nonce check when this route is visited just set
327
-     *            'require_nonce' to FALSE
328
-     *            )
329
-     * )
330
-     *
331
-     * @abstract
332
-     * @access protected
333
-     * @return void
334
-     */
335
-    abstract protected function _set_page_config();
336
-
337
-
338
-
339
-
340
-
341
-    /** end sample help_tour methods **/
342
-    /**
343
-     * _add_screen_options
344
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
345
-     * Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options to a particular view.
346
-     *
347
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
348
-     *         see also WP_Screen object documents...
349
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
350
-     * @abstract
351
-     * @access protected
352
-     * @return void
353
-     */
354
-    abstract protected function _add_screen_options();
355
-
356
-
357
-
358
-    /**
359
-     * _add_feature_pointers
360
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
361
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a particular view.
362
-     * Note: this is just a placeholder for now.  Implementation will come down the road
363
-     * See: WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be extended) also see:
364
-     *
365
-     * @link   http://eamann.com/tech/wordpress-portland/
366
-     * @abstract
367
-     * @access protected
368
-     * @return void
369
-     */
370
-    abstract protected function _add_feature_pointers();
371
-
372
-
373
-
374
-    /**
375
-     * load_scripts_styles
376
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific scripts/styles
377
-     * per view by putting them in a dynamic function in this format (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
378
-     *
379
-     * @abstract
380
-     * @access public
381
-     * @return void
382
-     */
383
-    abstract public function load_scripts_styles();
384
-
385
-
386
-
387
-    /**
388
-     * admin_init
389
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to all pages/views loaded by child class.
390
-     *
391
-     * @abstract
392
-     * @access public
393
-     * @return void
394
-     */
395
-    abstract public function admin_init();
396
-
397
-
398
-
399
-    /**
400
-     * admin_notices
401
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to all pages/views loaded by child class.
402
-     *
403
-     * @abstract
404
-     * @access public
405
-     * @return void
406
-     */
407
-    abstract public function admin_notices();
408
-
409
-
410
-
411
-    /**
412
-     * admin_footer_scripts
413
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method will apply to all pages/views loaded by child class.
414
-     *
415
-     * @access public
416
-     * @return void
417
-     */
418
-    abstract public function admin_footer_scripts();
419
-
420
-
421
-
422
-    /**
423
-     * admin_footer
424
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will apply to all pages/views loaded by child class.
425
-     *
426
-     * @access  public
427
-     * @return void
428
-     */
429
-    public function admin_footer()
430
-    {
431
-    }
432
-
433
-
434
-
435
-    /**
436
-     * _global_ajax_hooks
437
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
438
-     * Note: within the ajax callback methods.
439
-     *
440
-     * @abstract
441
-     * @access protected
442
-     * @return void
443
-     */
444
-    protected function _global_ajax_hooks()
445
-    {
446
-        //for lazy loading of metabox content
447
-        add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
448
-    }
449
-
450
-
451
-
452
-    public function ajax_metabox_content()
453
-    {
454
-        $contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
455
-        $url = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
456
-        self::cached_rss_display($contentid, $url);
457
-        wp_die();
458
-    }
459
-
460
-
461
-
462
-    /**
463
-     * _page_setup
464
-     * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested doesn't match the object.
465
-     *
466
-     * @final
467
-     * @access protected
468
-     * @return void
469
-     */
470
-    final protected function _page_setup()
471
-    {
472
-        //requires?
473
-        //admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
474
-        add_action('admin_init', array($this, 'admin_init_global'), 5);
475
-        //next verify if we need to load anything...
476
-        $this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
477
-        $this->page_folder = strtolower(str_replace('_Admin_Page', '', str_replace('Extend_', '', get_class($this))));
478
-        global $ee_menu_slugs;
479
-        $ee_menu_slugs = (array)$ee_menu_slugs;
480
-        if (( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page])) && ! defined('DOING_AJAX')) {
481
-            return;
482
-        }
483
-        // becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
484
-        if (isset($this->_req_data['action2']) && $this->_req_data['action'] == -1) {
485
-            $this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] != -1 ? $this->_req_data['action2'] : $this->_req_data['action'];
486
-        }
487
-        // then set blank or -1 action values to 'default'
488
-        $this->_req_action = isset($this->_req_data['action']) && ! empty($this->_req_data['action']) && $this->_req_data['action'] != -1 ? sanitize_key($this->_req_data['action']) : 'default';
489
-        //if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.  This covers cases where we're coming in from a list table that isn't on the default route.
490
-        $this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route']) ? $this->_req_data['route'] : $this->_req_action;
491
-        //however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
492
-        $this->_req_action = defined('DOING_AJAX') && isset($this->_req_data['route']) ? $this->_req_data['route'] : $this->_req_action;
493
-        $this->_current_view = $this->_req_action;
494
-        $this->_req_nonce = $this->_req_action . '_nonce';
495
-        $this->_define_page_props();
496
-        $this->_current_page_view_url = add_query_arg(array('page' => $this->_current_page, 'action' => $this->_current_view), $this->_admin_base_url);
497
-        //default things
498
-        $this->_default_espresso_metaboxes = array('_espresso_news_post_box', '_espresso_links_post_box', '_espresso_ratings_request', '_espresso_sponsors_post_box');
499
-        //set page configs
500
-        $this->_set_page_routes();
501
-        $this->_set_page_config();
502
-        //let's include any referrer data in our default_query_args for this route for "stickiness".
503
-        if (isset($this->_req_data['wp_referer'])) {
504
-            $this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
505
-        }
506
-        //for caffeinated and other extended functionality.  If there is a _extend_page_config method then let's run that to modify the all the various page configuration arrays
507
-        if (method_exists($this, '_extend_page_config')) {
508
-            $this->_extend_page_config();
509
-        }
510
-        //for CPT and other extended functionality. If there is an _extend_page_config_for_cpt then let's run that to modify all the various page configuration arrays.
511
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
512
-            $this->_extend_page_config_for_cpt();
513
-        }
514
-        //filter routes and page_config so addons can add their stuff. Filtering done per class
515
-        $this->_page_routes = apply_filters('FHEE__' . get_class($this) . '__page_setup__page_routes', $this->_page_routes, $this);
516
-        $this->_page_config = apply_filters('FHEE__' . get_class($this) . '__page_setup__page_config', $this->_page_config, $this);
517
-        //if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
518
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
519
-            add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view), 10, 2);
520
-        }
521
-        //next route only if routing enabled
522
-        if ($this->_routing && ! defined('DOING_AJAX')) {
523
-            $this->_verify_routes();
524
-            //next let's just check user_access and kill if no access
525
-            $this->check_user_access();
526
-            if ($this->_is_UI_request) {
527
-                //admin_init stuff - global, all views for this page class, specific view
528
-                add_action('admin_init', array($this, 'admin_init'), 10);
529
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
530
-                    add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
531
-                }
532
-            } else {
533
-                //hijack regular WP loading and route admin request immediately
534
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
535
-                $this->route_admin_request();
536
-            }
537
-        }
538
-    }
539
-
540
-
541
-
542
-    /**
543
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
544
-     *
545
-     * @access private
546
-     * @return void
547
-     */
548
-    private function _do_other_page_hooks()
549
-    {
550
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
551
-        foreach ($registered_pages as $page) {
552
-            //now let's setup the file name and class that should be present
553
-            $classname = str_replace('.class.php', '', $page);
554
-            //autoloaders should take care of loading file
555
-            if ( ! class_exists($classname)) {
556
-                $error_msg[] = sprintf( esc_html__('Something went wrong with loading the %s admin hooks page.', 'event_espresso'), $page);
557
-                $error_msg[] = $error_msg[0]
558
-                               . "\r\n"
559
-                               . sprintf( esc_html__('There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
560
-                                'event_espresso'), $page, '<br />', '<strong>' . $classname . '</strong>');
561
-                throw new EE_Error(implode('||', $error_msg));
562
-            }
563
-            $a = new ReflectionClass($classname);
564
-            //notice we are passing the instance of this class to the hook object.
565
-            $hookobj[] = $a->newInstance($this);
566
-        }
567
-    }
568
-
569
-
570
-
571
-    public function load_page_dependencies()
572
-    {
573
-        try {
574
-            $this->_load_page_dependencies();
575
-        } catch (EE_Error $e) {
576
-            $e->get_error();
577
-        }
578
-    }
579
-
580
-
581
-
582
-    /**
583
-     * load_page_dependencies
584
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
585
-     *
586
-     * @access public
587
-     * @return void
588
-     */
589
-    protected function _load_page_dependencies()
590
-    {
591
-        //let's set the current_screen and screen options to override what WP set
592
-        $this->_current_screen = get_current_screen();
593
-        //load admin_notices - global, page class, and view specific
594
-        add_action('admin_notices', array($this, 'admin_notices_global'), 5);
595
-        add_action('admin_notices', array($this, 'admin_notices'), 10);
596
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
597
-            add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
598
-        }
599
-        //load network admin_notices - global, page class, and view specific
600
-        add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
601
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
602
-            add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
603
-        }
604
-        //this will save any per_page screen options if they are present
605
-        $this->_set_per_page_screen_options();
606
-        //setup list table properties
607
-        $this->_set_list_table();
608
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.  However in some cases the metaboxes will need to be added within a route handling callback.
609
-        $this->_add_registered_meta_boxes();
610
-        $this->_add_screen_columns();
611
-        //add screen options - global, page child class, and view specific
612
-        $this->_add_global_screen_options();
613
-        $this->_add_screen_options();
614
-        if (method_exists($this, '_add_screen_options_' . $this->_current_view)) {
615
-            call_user_func(array($this, '_add_screen_options_' . $this->_current_view));
616
-        }
617
-        //add help tab(s) and tours- set via page_config and qtips.
618
-        $this->_add_help_tour();
619
-        $this->_add_help_tabs();
620
-        $this->_add_qtips();
621
-        //add feature_pointers - global, page child class, and view specific
622
-        $this->_add_feature_pointers();
623
-        $this->_add_global_feature_pointers();
624
-        if (method_exists($this, '_add_feature_pointer_' . $this->_current_view)) {
625
-            call_user_func(array($this, '_add_feature_pointer_' . $this->_current_view));
626
-        }
627
-        //enqueue scripts/styles - global, page class, and view specific
628
-        add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
629
-        add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
630
-        if (method_exists($this, 'load_scripts_styles_' . $this->_current_view)) {
631
-            add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles_' . $this->_current_view), 15);
632
-        }
633
-        add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
634
-        //admin_print_footer_scripts - global, page child class, and view specific.  NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.  In most cases that's doing_it_wrong().  But adding hidden container elements etc. is a good use case. Notice the late priority we're giving these
635
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
636
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
637
-        if (method_exists($this, 'admin_footer_scripts_' . $this->_current_view)) {
638
-            add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_' . $this->_current_view), 101);
639
-        }
640
-        //admin footer scripts
641
-        add_action('admin_footer', array($this, 'admin_footer_global'), 99);
642
-        add_action('admin_footer', array($this, 'admin_footer'), 100);
643
-        if (method_exists($this, 'admin_footer_' . $this->_current_view)) {
644
-            add_action('admin_footer', array($this, 'admin_footer_' . $this->_current_view), 101);
645
-        }
646
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
647
-        //targeted hook
648
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load__' . $this->page_slug . '__' . $this->_req_action);
649
-    }
650
-
651
-
652
-
653
-    /**
654
-     * _set_defaults
655
-     * This sets some global defaults for class properties.
656
-     */
657
-    private function _set_defaults()
658
-    {
659
-        $this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = $this->_event = $this->_template_path = $this->_column_template_path = null;
660
-        $this->_nav_tabs = $this_views = $this->_page_routes = $this->_page_config = $this->_default_route_query_args = array();
661
-        $this->default_nav_tab_name = 'overview';
662
-        //init template args
663
-        $this->_template_args = array(
664
-                'admin_page_header'  => '',
665
-                'admin_page_content' => '',
666
-                'post_body_content'  => '',
667
-                'before_list_table'  => '',
668
-                'after_list_table'   => '',
669
-        );
670
-    }
671
-
672
-
673
-
674
-    /**
675
-     * route_admin_request
676
-     *
677
-     * @see    _route_admin_request()
678
-     * @access public
679
-     * @return void|exception error
680
-     */
681
-    public function route_admin_request()
682
-    {
683
-        try {
684
-            $this->_route_admin_request();
685
-        } catch (EE_Error $e) {
686
-            $e->get_error();
687
-        }
688
-    }
689
-
690
-
691
-
692
-    public function set_wp_page_slug($wp_page_slug)
693
-    {
694
-        $this->_wp_page_slug = $wp_page_slug;
695
-        //if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
696
-        if (is_network_admin()) {
697
-            $this->_wp_page_slug .= '-network';
698
-        }
699
-    }
700
-
701
-
702
-
703
-    /**
704
-     * _verify_routes
705
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so we know if we need to drop out.
706
-     *
707
-     * @access protected
708
-     * @return void
709
-     */
710
-    protected function _verify_routes()
711
-    {
712
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
713
-        if ( ! $this->_current_page && ! defined('DOING_AJAX')) {
714
-            return false;
715
-        }
716
-        $this->_route = false;
717
-        $func = false;
718
-        $args = array();
719
-        // check that the page_routes array is not empty
720
-        if (empty($this->_page_routes)) {
721
-            // user error msg
722
-            $error_msg = sprintf(__('No page routes have been set for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
723
-            // developer error msg
724
-            $error_msg .= '||' . $error_msg . __(' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.', 'event_espresso');
725
-            throw new EE_Error($error_msg);
726
-        }
727
-        // and that the requested page route exists
728
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
729
-            $this->_route = $this->_page_routes[$this->_req_action];
730
-            $this->_route_config = isset($this->_page_config[$this->_req_action]) ? $this->_page_config[$this->_req_action] : array();
731
-        } else {
732
-            // user error msg
733
-            $error_msg = sprintf(__('The requested page route does not exist for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
734
-            // developer error msg
735
-            $error_msg .= '||' . $error_msg . sprintf(__(' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.', 'event_espresso'), $this->_req_action);
736
-            throw new EE_Error($error_msg);
737
-        }
738
-        // and that a default route exists
739
-        if ( ! array_key_exists('default', $this->_page_routes)) {
740
-            // user error msg
741
-            $error_msg = sprintf(__('A default page route has not been set for the % admin page.', 'event_espresso'), $this->_admin_page_title);
742
-            // developer error msg
743
-            $error_msg .= '||' . $error_msg . __(' Create a key in the "_page_routes" array named "default" and set its value to your default page method.', 'event_espresso');
744
-            throw new EE_Error($error_msg);
745
-        }
746
-        //first lets' catch if the UI request has EVER been set.
747
-        if ($this->_is_UI_request === null) {
748
-            //lets set if this is a UI request or not.
749
-            $this->_is_UI_request = ( ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true) ? true : false;
750
-            //wait a minute... we might have a noheader in the route array
751
-            $this->_is_UI_request = is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader'] ? false : $this->_is_UI_request;
752
-        }
753
-        $this->_set_current_labels();
754
-    }
755
-
756
-
757
-
758
-    /**
759
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
760
-     *
761
-     * @param  string $route the route name we're verifying
762
-     * @return mixed  (bool|Exception)      we'll throw an exception if this isn't a valid route.
763
-     */
764
-    protected function _verify_route($route)
765
-    {
766
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
767
-            return true;
768
-        } else {
769
-            // user error msg
770
-            $error_msg = sprintf(__('The given page route does not exist for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
771
-            // developer error msg
772
-            $error_msg .= '||' . $error_msg . sprintf(__(' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property', 'event_espresso'), $route);
773
-            throw new EE_Error($error_msg);
774
-        }
775
-    }
776
-
777
-
778
-
779
-    /**
780
-     * perform nonce verification
781
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces using this method (and save retyping!)
782
-     *
783
-     * @param  string $nonce     The nonce sent
784
-     * @param  string $nonce_ref The nonce reference string (name0)
785
-     * @return mixed (bool|die)
786
-     */
787
-    protected function _verify_nonce($nonce, $nonce_ref)
788
-    {
789
-        // verify nonce against expected value
790
-        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
791
-            // these are not the droids you are looking for !!!
792
-            $msg = sprintf(__('%sNonce Fail.%s', 'event_espresso'), '<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">', '</a>');
793
-            if (WP_DEBUG) {
794
-                $msg .= "\n  " . sprintf(__('In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!', 'event_espresso'), __CLASS__);
795
-            }
796
-            if ( ! defined('DOING_AJAX')) {
797
-                wp_die($msg);
798
-            } else {
799
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
800
-                $this->_return_json();
801
-            }
802
-        }
803
-    }
804
-
805
-
806
-
807
-    /**
808
-     * _route_admin_request()
809
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
810
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
811
-     * in the page routes and then will try to load the corresponding method.
812
-     *
813
-     * @access protected
814
-     * @return void
815
-     * @throws \EE_Error
816
-     */
817
-    protected function _route_admin_request()
818
-    {
819
-        if ( ! $this->_is_UI_request) {
820
-            $this->_verify_routes();
821
-        }
822
-        $nonce_check = isset($this->_route_config['require_nonce'])
823
-            ? $this->_route_config['require_nonce']
824
-            : true;
825
-        if ($this->_req_action !== 'default' && $nonce_check) {
826
-            // set nonce from post data
827
-            $nonce = isset($this->_req_data[$this->_req_nonce])
828
-                ? sanitize_text_field($this->_req_data[$this->_req_nonce])
829
-                : '';
830
-            $this->_verify_nonce($nonce, $this->_req_nonce);
831
-        }
832
-        //set the nav_tabs array but ONLY if this is  UI_request
833
-        if ($this->_is_UI_request) {
834
-            $this->_set_nav_tabs();
835
-        }
836
-        // grab callback function
837
-        $func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
838
-        // check if callback has args
839
-        $args = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
840
-        $error_msg = '';
841
-        // action right before calling route
842
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
843
-        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
844
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
845
-        }
846
-        // right before calling the route, let's remove _wp_http_referer from the
847
-        // $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
848
-        $_SERVER['REQUEST_URI'] = remove_query_arg('_wp_http_referer', wp_unslash($_SERVER['REQUEST_URI']));
849
-        if ( ! empty($func)) {
850
-            if (is_array($func)) {
851
-                list($class, $method) = $func;
852
-            } else if (strpos($func, '::') !== false) {
853
-                list($class, $method) = explode('::', $func);
854
-            } else {
855
-                $class = $this;
856
-                $method = $func;
857
-            }
858
-            if ( ! (is_object($class) && $class === $this)) {
859
-                // send along this admin page object for access by addons.
860
-                $args['admin_page_object'] = $this;
861
-            }
862
-
863
-            if (
864
-                //is it a method on a class that doesn't work?
865
-                (
866
-                    (
867
-                        method_exists($class, $method)
868
-                        && call_user_func_array(array($class, $method), $args) === false
869
-                    )
870
-                    && (
871
-                        //is it a standalone function that doesn't work?
872
-                        function_exists($method)
873
-                        && call_user_func_array($func, array_merge(array('admin_page_object' => $this), $args)) === false
874
-                    )
875
-                )
876
-                || (
877
-                    //is it neither a class method NOR a standalone function?
878
-                    ! method_exists($class, $method)
879
-                    && ! function_exists($method)
880
-                )
881
-            ) {
882
-                // user error msg
883
-                $error_msg = __('An error occurred. The  requested page route could not be found.', 'event_espresso');
884
-                // developer error msg
885
-                $error_msg .= '||';
886
-                $error_msg .= sprintf(
887
-                    __(
888
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
889
-                        'event_espresso'
890
-                    ),
891
-                    $method
892
-                );
893
-            }
894
-            if ( ! empty($error_msg)) {
895
-                throw new EE_Error($error_msg);
896
-            }
897
-        }
898
-        //if we've routed and this route has a no headers route AND a sent_headers_route, then we need to reset the routing properties to the new route.
899
-        //now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
900
-        if ($this->_is_UI_request === false
901
-            && is_array($this->_route)
902
-            && ! empty($this->_route['headers_sent_route'])
903
-        ) {
904
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
905
-        }
906
-    }
907
-
908
-
909
-
910
-    /**
911
-     * This method just allows the resetting of page properties in the case where a no headers
912
-     * route redirects to a headers route in its route config.
913
-     *
914
-     * @since   4.3.0
915
-     * @param  string $new_route New (non header) route to redirect to.
916
-     * @return   void
917
-     */
918
-    protected function _reset_routing_properties($new_route)
919
-    {
920
-        $this->_is_UI_request = true;
921
-        //now we set the current route to whatever the headers_sent_route is set at
922
-        $this->_req_data['action'] = $new_route;
923
-        //rerun page setup
924
-        $this->_page_setup();
925
-    }
926
-
927
-
928
-
929
-    /**
930
-     * _add_query_arg
931
-     * adds nonce to array of arguments then calls WP add_query_arg function
932
-     *(internally just uses EEH_URL's function with the same name)
933
-     *
934
-     * @access public
935
-     * @param array  $args
936
-     * @param string $url
937
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the generated
938
-     *                                        url in an associative array indexed by the key 'wp_referer';
939
-     *                                        Example usage:
940
-     *                                        If the current page is:
941
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
942
-     *                                        &action=default&event_id=20&month_range=March%202015
943
-     *                                        &_wpnonce=5467821
944
-     *                                        and you call:
945
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
946
-     *                                        array(
947
-     *                                        'action' => 'resend_something',
948
-     *                                        'page=>espresso_registrations'
949
-     *                                        ),
950
-     *                                        $some_url,
951
-     *                                        true
952
-     *                                        );
953
-     *                                        It will produce a url in this structure:
954
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
955
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
956
-     *                                        month_range]=March%202015
957
-     * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
958
-     * @return string
959
-     */
960
-    public static function add_query_args_and_nonce($args = array(), $url = false, $sticky = false, $exclude_nonce = false)
961
-    {
962
-        //if there is a _wp_http_referer include the values from the request but only if sticky = true
963
-        if ($sticky) {
964
-            $request = $_REQUEST;
965
-            unset($request['_wp_http_referer']);
966
-            unset($request['wp_referer']);
967
-            foreach ($request as $key => $value) {
968
-                //do not add nonces
969
-                if (strpos($key, 'nonce') !== false) {
970
-                    continue;
971
-                }
972
-                $args['wp_referer[' . $key . ']'] = $value;
973
-            }
974
-        }
975
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
976
-    }
977
-
978
-
979
-
980
-    /**
981
-     * This returns a generated link that will load the related help tab.
982
-     *
983
-     * @param  string $help_tab_id the id for the connected help tab
984
-     * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
985
-     * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
986
-     * @uses EEH_Template::get_help_tab_link()
987
-     * @return string              generated link
988
-     */
989
-    protected function _get_help_tab_link($help_tab_id, $icon_style = false, $help_text = false)
990
-    {
991
-        return EEH_Template::get_help_tab_link($help_tab_id, $this->page_slug, $this->_req_action, $icon_style, $help_text);
992
-    }
993
-
994
-
995
-
996
-    /**
997
-     * _add_help_tabs
998
-     * Note child classes define their help tabs within the page_config array.
999
-     *
1000
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1001
-     * @access protected
1002
-     * @return void
1003
-     */
1004
-    protected function _add_help_tabs()
1005
-    {
1006
-        $tour_buttons = '';
1007
-        if (isset($this->_page_config[$this->_req_action])) {
1008
-            $config = $this->_page_config[$this->_req_action];
1009
-            //is there a help tour for the current route?  if there is let's setup the tour buttons
1010
-            if (isset($this->_help_tour[$this->_req_action])) {
1011
-                $tb = array();
1012
-                $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1013
-                foreach ($this->_help_tour['tours'] as $tour) {
1014
-                    //if this is the end tour then we don't need to setup a button
1015
-                    if ($tour instanceof EE_Help_Tour_final_stop) {
1016
-                        continue;
1017
-                    }
1018
-                    $tb[] = '<button id="trigger-tour-' . $tour->get_slug() . '" class="button-primary trigger-ee-help-tour">' . $tour->get_label() . '</button>';
1019
-                }
1020
-                $tour_buttons .= implode('<br />', $tb);
1021
-                $tour_buttons .= '</div></div>';
1022
-            }
1023
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1024
-            if (is_array($config) && isset($config['help_sidebar'])) {
1025
-                //check that the callback given is valid
1026
-                if ( ! method_exists($this, $config['help_sidebar'])) {
1027
-                    throw new EE_Error(sprintf(__('The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1028
-                            'event_espresso'), $config['help_sidebar'], get_class($this)));
1029
-                }
1030
-                $content = apply_filters('FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar', call_user_func(array($this, $config['help_sidebar'])));
1031
-                $content .= $tour_buttons; //add help tour buttons.
1032
-                //do we have any help tours setup?  Cause if we do we want to add the buttons
1033
-                $this->_current_screen->set_help_sidebar($content);
1034
-            }
1035
-            //if we DON'T have config help sidebar and there ARE toure buttons then we'll just add the tour buttons to the sidebar.
1036
-            if ( ! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1037
-                $this->_current_screen->set_help_sidebar($tour_buttons);
1038
-            }
1039
-            //handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1040
-            if ( ! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1041
-                $_ht['id'] = $this->page_slug;
1042
-                $_ht['title'] = __('Help Tours', 'event_espresso');
1043
-                $_ht['content'] = '<p>' . __('The buttons to the right allow you to start/restart any help tours available for this page', 'event_espresso') . '</p>';
1044
-                $this->_current_screen->add_help_tab($_ht);
1045
-            }/**/
1046
-            if ( ! isset($config['help_tabs'])) {
1047
-                return;
1048
-            } //no help tabs for this route
1049
-            foreach ((array)$config['help_tabs'] as $tab_id => $cfg) {
1050
-                //we're here so there ARE help tabs!
1051
-                //make sure we've got what we need
1052
-                if ( ! isset($cfg['title'])) {
1053
-                    throw new EE_Error(__('The _page_config array is not set up properly for help tabs.  It is missing a title', 'event_espresso'));
1054
-                }
1055
-                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1056
-                    throw new EE_Error(__('The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1057
-                            'event_espresso'));
1058
-                }
1059
-                //first priority goes to content.
1060
-                if ( ! empty($cfg['content'])) {
1061
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1062
-                    //second priority goes to filename
1063
-                } else if ( ! empty($cfg['filename'])) {
1064
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1065
-                    //it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1066
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES . basename($this->_get_dir()) . '/help_tabs/' . $cfg['filename'] . '.help_tab.php' : $file_path;
1067
-                    //if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1068
-                    if ( ! is_readable($file_path) && ! isset($cfg['callback'])) {
1069
-                        EE_Error::add_error(sprintf(__('The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1070
-                                'event_espresso'), $tab_id, key($config), $file_path), __FILE__, __FUNCTION__, __LINE__);
1071
-                        return;
1072
-                    }
1073
-                    $template_args['admin_page_obj'] = $this;
1074
-                    $content = EEH_Template::display_template($file_path, $template_args, true);
1075
-                } else {
1076
-                    $content = '';
1077
-                }
1078
-                //check if callback is valid
1079
-                if (empty($content) && ( ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback']))) {
1080
-                    EE_Error::add_error(sprintf(__('The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1081
-                            'event_espresso'), $cfg['title']), __FILE__, __FUNCTION__, __LINE__);
1082
-                    return;
1083
-                }
1084
-                //setup config array for help tab method
1085
-                $id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1086
-                $_ht = array(
1087
-                        'id'       => $id,
1088
-                        'title'    => $cfg['title'],
1089
-                        'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1090
-                        'content'  => $content,
1091
-                );
1092
-                $this->_current_screen->add_help_tab($_ht);
1093
-            }
1094
-        }
1095
-    }
1096
-
1097
-
1098
-
1099
-    /**
1100
-     * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is an array with properties for setting up usage of the joyride plugin
1101
-     *
1102
-     * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1103
-     * @see    instructions regarding the format and construction of the "help_tour" array element is found in the _set_page_config() comments
1104
-     * @access protected
1105
-     * @return void
1106
-     */
1107
-    protected function _add_help_tour()
1108
-    {
1109
-        $tours = array();
1110
-        $this->_help_tour = array();
1111
-        //exit early if help tours are turned off globally
1112
-        if ( ! EE_Registry::instance()->CFG->admin->help_tour_activation || (defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)) {
1113
-            return;
1114
-        }
1115
-        //loop through _page_config to find any help_tour defined
1116
-        foreach ($this->_page_config as $route => $config) {
1117
-            //we're only going to set things up for this route
1118
-            if ($route !== $this->_req_action) {
1119
-                continue;
1120
-            }
1121
-            if (isset($config['help_tour'])) {
1122
-                foreach ($config['help_tour'] as $tour) {
1123
-                    $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1124
-                    //let's see if we can get that file... if not its possible this is a decaf route not set in caffienated so lets try and get the caffeinated equivalent
1125
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES . basename($this->_get_dir()) . '/help_tours/' . $tour . '.class.php' : $file_path;
1126
-                    //if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1127
-                    if ( ! is_readable($file_path)) {
1128
-                        EE_Error::add_error(sprintf(__('The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling', 'event_espresso'),
1129
-                                $file_path, $tour), __FILE__, __FUNCTION__, __LINE__);
1130
-                        return;
1131
-                    }
1132
-                    require_once $file_path;
1133
-                    if ( ! class_exists($tour)) {
1134
-                        $error_msg[] = sprintf(__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'), $tour);
1135
-                        $error_msg[] = $error_msg[0] . "\r\n" . sprintf(__('There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1136
-                                        'event_espresso'), $tour, '<br />', $tour, $this->_req_action, get_class($this));
1137
-                        throw new EE_Error(implode('||', $error_msg));
1138
-                    }
1139
-                    $a = new ReflectionClass($tour);
1140
-                    $tour_obj = $a->newInstance($this->_is_caf);
1141
-                    $tours[] = $tour_obj;
1142
-                    $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1143
-                }
1144
-                //let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1145
-                $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1146
-                $tours[] = $end_stop_tour;
1147
-                $this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1148
-            }
1149
-        }
1150
-        if ( ! empty($tours)) {
1151
-            $this->_help_tour['tours'] = $tours;
1152
-        }
1153
-        //thats it!  Now that the $_help_tours property is set (or not) the scripts and html should be taken care of automatically.
1154
-    }
1155
-
1156
-
1157
-
1158
-    /**
1159
-     * This simply sets up any qtips that have been defined in the page config
1160
-     *
1161
-     * @access protected
1162
-     * @return void
1163
-     */
1164
-    protected function _add_qtips()
1165
-    {
1166
-        if (isset($this->_route_config['qtips'])) {
1167
-            $qtips = (array)$this->_route_config['qtips'];
1168
-            //load qtip loader
1169
-            $path = array(
1170
-                    $this->_get_dir() . '/qtips/',
1171
-                    EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1172
-            );
1173
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1174
-        }
1175
-    }
1176
-
1177
-
1178
-
1179
-    /**
1180
-     * _set_nav_tabs
1181
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you wish to add additional tabs or modify accordingly.
1182
-     *
1183
-     * @access protected
1184
-     * @return void
1185
-     */
1186
-    protected function _set_nav_tabs()
1187
-    {
1188
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1189
-        $i = 0;
1190
-        foreach ($this->_page_config as $slug => $config) {
1191
-            if ( ! is_array($config) || (is_array($config) && (isset($config['nav']) && ! $config['nav']) || ! isset($config['nav']))) {
1192
-                continue;
1193
-            } //no nav tab for this config
1194
-            //check for persistent flag
1195
-            if (isset($config['nav']['persistent']) && ! $config['nav']['persistent'] && $slug !== $this->_req_action) {
1196
-                continue;
1197
-            } //nav tab is only to appear when route requested.
1198
-            if ( ! $this->check_user_access($slug, true)) {
1199
-                continue;
1200
-            } //no nav tab becasue current user does not have access.
1201
-            $css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1202
-            $this->_nav_tabs[$slug] = array(
1203
-                    'url'       => isset($config['nav']['url']) ? $config['nav']['url'] : self::add_query_args_and_nonce(array('action' => $slug), $this->_admin_base_url),
1204
-                    'link_text' => isset($config['nav']['label']) ? $config['nav']['label'] : ucwords(str_replace('_', ' ', $slug)),
1205
-                    'css_class' => $this->_req_action == $slug ? $css_class . 'nav-tab-active' : $css_class,
1206
-                    'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1207
-            );
1208
-            $i++;
1209
-        }
1210
-        //if $this->_nav_tabs is empty then lets set the default
1211
-        if (empty($this->_nav_tabs)) {
1212
-            $this->_nav_tabs[$this->default_nav_tab_name] = array(
1213
-                    'url'       => $this->admin_base_url,
1214
-                    'link_text' => ucwords(str_replace('_', ' ', $this->default_nav_tab_name)),
1215
-                    'css_class' => 'nav-tab-active',
1216
-                    'order'     => 10,
1217
-            );
1218
-        }
1219
-        //now let's sort the tabs according to order
1220
-        usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1221
-    }
1222
-
1223
-
1224
-
1225
-    /**
1226
-     * _set_current_labels
1227
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes property array
1228
-     *
1229
-     * @access private
1230
-     * @return void
1231
-     */
1232
-    private function _set_current_labels()
1233
-    {
1234
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1235
-            foreach ($this->_route_config['labels'] as $label => $text) {
1236
-                if (is_array($text)) {
1237
-                    foreach ($text as $sublabel => $subtext) {
1238
-                        $this->_labels[$label][$sublabel] = $subtext;
1239
-                    }
1240
-                } else {
1241
-                    $this->_labels[$label] = $text;
1242
-                }
1243
-            }
1244
-        }
1245
-    }
1246
-
1247
-
1248
-
1249
-    /**
1250
-     *        verifies user access for this admin page
1251
-     *
1252
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1253
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just return false if verify fail.
1254
-     * @return        BOOL|wp_die()
1255
-     */
1256
-    public function check_user_access($route_to_check = '', $verify_only = false)
1257
-    {
1258
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1259
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1260
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check]) && is_array($this->_page_routes[$route_to_check]) && ! empty($this->_page_routes[$route_to_check]['capability'])
1261
-                ? $this->_page_routes[$route_to_check]['capability'] : null;
1262
-        if (empty($capability) && empty($route_to_check)) {
1263
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options' : $this->_route['capability'];
1264
-        } else {
1265
-            $capability = empty($capability) ? 'manage_options' : $capability;
1266
-        }
1267
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1268
-        if (( ! function_exists('is_admin') || ! EE_Registry::instance()->CAP->current_user_can($capability, $this->page_slug . '_' . $route_to_check, $id)) && ! defined('DOING_AJAX')) {
1269
-            if ($verify_only) {
1270
-                return false;
1271
-            } else {
1272
-                if ( is_user_logged_in() ) {
1273
-                    wp_die(__('You do not have access to this route.', 'event_espresso'));
1274
-                } else {
1275
-                    return false;
1276
-                }
1277
-            }
1278
-        }
1279
-        return true;
1280
-    }
1281
-
1282
-
1283
-
1284
-    /**
1285
-     * admin_init_global
1286
-     * This runs all the code that we want executed within the WP admin_init hook.
1287
-     * This method executes for ALL EE Admin pages.
1288
-     *
1289
-     * @access public
1290
-     * @return void
1291
-     */
1292
-    public function admin_init_global()
1293
-    {
1294
-    }
1295
-
1296
-
1297
-
1298
-    /**
1299
-     * wp_loaded_global
1300
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an EE_Admin page and will execute on every EE Admin Page load
1301
-     *
1302
-     * @access public
1303
-     * @return void
1304
-     */
1305
-    public function wp_loaded()
1306
-    {
1307
-    }
1308
-
1309
-
1310
-
1311
-    /**
1312
-     * admin_notices
1313
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on ALL EE_Admin pages.
1314
-     *
1315
-     * @access public
1316
-     * @return void
1317
-     */
1318
-    public function admin_notices_global()
1319
-    {
1320
-        $this->_display_no_javascript_warning();
1321
-        $this->_display_espresso_notices();
1322
-    }
1323
-
1324
-
1325
-
1326
-    public function network_admin_notices_global()
1327
-    {
1328
-        $this->_display_no_javascript_warning();
1329
-        $this->_display_espresso_notices();
1330
-    }
1331
-
1332
-
1333
-
1334
-    /**
1335
-     * admin_footer_scripts_global
1336
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method will apply on ALL EE_Admin pages.
1337
-     *
1338
-     * @access public
1339
-     * @return void
1340
-     */
1341
-    public function admin_footer_scripts_global()
1342
-    {
1343
-        $this->_add_admin_page_ajax_loading_img();
1344
-        $this->_add_admin_page_overlay();
1345
-        //if metaboxes are present we need to add the nonce field
1346
-        if ((isset($this->_route_config['metaboxes']) || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes']) || isset($this->_route_config['list_table']))) {
1347
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1348
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1349
-        }
1350
-    }
1351
-
1352
-
1353
-
1354
-    /**
1355
-     * admin_footer_global
1356
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particluar method will apply on ALL EE_Admin Pages.
1357
-     *
1358
-     * @access  public
1359
-     * @return  void
1360
-     */
1361
-    public function admin_footer_global()
1362
-    {
1363
-        //dialog container for dialog helper
1364
-        $d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1365
-        $d_cont .= '<div class="ee-notices"></div>';
1366
-        $d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1367
-        $d_cont .= '</div>';
1368
-        echo $d_cont;
1369
-        //help tour stuff?
1370
-        if (isset($this->_help_tour[$this->_req_action])) {
1371
-            echo implode('<br />', $this->_help_tour[$this->_req_action]);
1372
-        }
1373
-        //current set timezone for timezone js
1374
-        echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1375
-    }
1376
-
1377
-
1378
-
1379
-    /**
1380
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then we'll use the retrieved array to output the content using the template.
1381
-     * For child classes:
1382
-     * If you want to have help popups then in your templates or your content you set "triggers" for the content using the "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method for
1383
-     * the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content for the
1384
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1385
-     *    'help_trigger_id' => array(
1386
-     *        'title' => __('localized title for popup', 'event_espresso'),
1387
-     *        'content' => __('localized content for popup', 'event_espresso')
1388
-     *    )
1389
-     * );
1390
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1391
-     *
1392
-     * @access protected
1393
-     * @return string content
1394
-     */
1395
-    protected function _set_help_popup_content($help_array = array(), $display = false)
1396
-    {
1397
-        $content = '';
1398
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1399
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php';
1400
-        //loop through the array and setup content
1401
-        foreach ($help_array as $trigger => $help) {
1402
-            //make sure the array is setup properly
1403
-            if ( ! isset($help['title']) || ! isset($help['content'])) {
1404
-                throw new EE_Error(__('Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1405
-                        'event_espresso'));
1406
-            }
1407
-            //we're good so let'd setup the template vars and then assign parsed template content to our content.
1408
-            $template_args = array(
1409
-                    'help_popup_id'      => $trigger,
1410
-                    'help_popup_title'   => $help['title'],
1411
-                    'help_popup_content' => $help['content'],
1412
-            );
1413
-            $content .= EEH_Template::display_template($template_path, $template_args, true);
1414
-        }
1415
-        if ($display) {
1416
-            echo $content;
1417
-        } else {
1418
-            return $content;
1419
-        }
1420
-    }
1421
-
1422
-
1423
-
1424
-    /**
1425
-     * All this does is retrive the help content array if set by the EE_Admin_Page child
1426
-     *
1427
-     * @access private
1428
-     * @return array properly formatted array for help popup content
1429
-     */
1430
-    private function _get_help_content()
1431
-    {
1432
-        //what is the method we're looking for?
1433
-        $method_name = '_help_popup_content_' . $this->_req_action;
1434
-        //if method doesn't exist let's get out.
1435
-        if ( ! method_exists($this, $method_name)) {
1436
-            return array();
1437
-        }
1438
-        //k we're good to go let's retrieve the help array
1439
-        $help_array = call_user_func(array($this, $method_name));
1440
-        //make sure we've got an array!
1441
-        if ( ! is_array($help_array)) {
1442
-            throw new EE_Error(__('Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.', 'event_espresso'));
1443
-        }
1444
-        return $help_array;
1445
-    }
1446
-
1447
-
1448
-
1449
-    /**
1450
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1451
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1452
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1453
-     *
1454
-     * @access protected
1455
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1456
-     * @param boolean $display    if false then we return the trigger string
1457
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1458
-     * @return string
1459
-     */
1460
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1461
-    {
1462
-        if (defined('DOING_AJAX')) {
1463
-            return;
1464
-        }
1465
-        //let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1466
-        $help_array = $this->_get_help_content();
1467
-        $help_content = '';
1468
-        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1469
-            $help_array[$trigger_id] = array(
1470
-                    'title'   => __('Missing Content', 'event_espresso'),
1471
-                    'content' => __('A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1472
-                            'event_espresso'),
1473
-            );
1474
-            $help_content = $this->_set_help_popup_content($help_array, false);
1475
-        }
1476
-        //let's setup the trigger
1477
-        $content = '<a class="ee-dialog" href="?height=' . $dimensions[0] . '&width=' . $dimensions[1] . '&inlineId=' . $trigger_id . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1478
-        $content = $content . $help_content;
1479
-        if ($display) {
1480
-            echo $content;
1481
-        } else {
1482
-            return $content;
1483
-        }
1484
-    }
1485
-
1486
-
1487
-
1488
-    /**
1489
-     * _add_global_screen_options
1490
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1491
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1492
-     *
1493
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1494
-     *         see also WP_Screen object documents...
1495
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1496
-     * @abstract
1497
-     * @access private
1498
-     * @return void
1499
-     */
1500
-    private function _add_global_screen_options()
1501
-    {
1502
-    }
1503
-
1504
-
1505
-
1506
-    /**
1507
-     * _add_global_feature_pointers
1508
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1509
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1510
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1511
-     *
1512
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be extended) also see:
1513
-     * @link   http://eamann.com/tech/wordpress-portland/
1514
-     * @abstract
1515
-     * @access protected
1516
-     * @return void
1517
-     */
1518
-    private function _add_global_feature_pointers()
1519
-    {
1520
-    }
1521
-
1522
-
1523
-
1524
-    /**
1525
-     * load_global_scripts_styles
1526
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1527
-     *
1528
-     * @return void
1529
-     */
1530
-    public function load_global_scripts_styles()
1531
-    {
1532
-        /** STYLES **/
1533
-        // add debugging styles
1534
-        if (WP_DEBUG) {
1535
-            add_action('admin_head', array($this, 'add_xdebug_style'));
1536
-        }
1537
-        // register all styles
1538
-        wp_register_style('espresso-ui-theme', EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css', array(), EVENT_ESPRESSO_VERSION);
1539
-        wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1540
-        //helpers styles
1541
-        wp_register_style('ee-text-links', EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css', array(), EVENT_ESPRESSO_VERSION);
1542
-        /** SCRIPTS **/
1543
-        //register all scripts
1544
-        wp_register_script('ee-dialog', EE_ADMIN_URL . 'assets/ee-dialog-helper.js', array('jquery', 'jquery-ui-draggable'), EVENT_ESPRESSO_VERSION, true);
1545
-        wp_register_script('ee_admin_js', EE_ADMIN_URL . 'assets/ee-admin-page.js', array('espresso_core', 'ee-parse-uri', 'ee-dialog'), EVENT_ESPRESSO_VERSION, true);
1546
-        wp_register_script('jquery-ui-timepicker-addon', EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js', array('jquery-ui-datepicker', 'jquery-ui-slider'), EVENT_ESPRESSO_VERSION, true);
1547
-        add_filter('FHEE_load_joyride', '__return_true');
1548
-        //script for sorting tables
1549
-        wp_register_script('espresso_ajax_table_sorting', EE_ADMIN_URL . "assets/espresso_ajax_table_sorting.js", array('ee_admin_js', 'jquery-ui-sortable'), EVENT_ESPRESSO_VERSION, true);
1550
-        //script for parsing uri's
1551
-        wp_register_script('ee-parse-uri', EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js', array(), EVENT_ESPRESSO_VERSION, true);
1552
-        //and parsing associative serialized form elements
1553
-        wp_register_script('ee-serialize-full-array', EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1554
-        //helpers scripts
1555
-        wp_register_script('ee-text-links', EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1556
-        wp_register_script('ee-moment-core', EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js', array(), EVENT_ESPRESSO_VERSION, true);
1557
-        wp_register_script('ee-moment', EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js', array('ee-moment-core'), EVENT_ESPRESSO_VERSION, true);
1558
-        wp_register_script('ee-datepicker', EE_ADMIN_URL . 'assets/ee-datepicker.js', array('jquery-ui-timepicker-addon', 'ee-moment'), EVENT_ESPRESSO_VERSION, true);
1559
-        //google charts
1560
-        wp_register_script('google-charts', 'https://www.gstatic.com/charts/loader.js', array(), EVENT_ESPRESSO_VERSION, false);
1561
-        // ENQUEUE ALL BASICS BY DEFAULT
1562
-        wp_enqueue_style('ee-admin-css');
1563
-        wp_enqueue_script('ee_admin_js');
1564
-        wp_enqueue_script('ee-accounting');
1565
-        wp_enqueue_script('jquery-validate');
1566
-        //taking care of metaboxes
1567
-        if (
1568
-            empty($this->_cpt_route)
1569
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1570
-        ) {
1571
-            wp_enqueue_script('dashboard');
1572
-        }
1573
-        // LOCALIZED DATA
1574
-        //localize script for ajax lazy loading
1575
-        $lazy_loader_container_ids = apply_filters('FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers', array('espresso_news_post_box_content'));
1576
-        wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1577
-        /**
1578
-         * help tour stuff
1579
-         */
1580
-        if ( ! empty($this->_help_tour)) {
1581
-            //register the js for kicking things off
1582
-            wp_enqueue_script('ee-help-tour', EE_ADMIN_URL . 'assets/ee-help-tour.js', array('jquery-joyride'), EVENT_ESPRESSO_VERSION, true);
1583
-            //setup tours for the js tour object
1584
-            foreach ($this->_help_tour['tours'] as $tour) {
1585
-                $tours[] = array(
1586
-                        'id'      => $tour->get_slug(),
1587
-                        'options' => $tour->get_options(),
1588
-                );
1589
-            }
1590
-            wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
1591
-            //admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
1592
-        }
1593
-    }
1594
-
1595
-
1596
-
1597
-    /**
1598
-     *        admin_footer_scripts_eei18n_js_strings
1599
-     *
1600
-     * @access        public
1601
-     * @return        void
1602
-     */
1603
-    public function admin_footer_scripts_eei18n_js_strings()
1604
-    {
1605
-        EE_Registry::$i18n_js_strings['ajax_url'] = WP_AJAX_URL;
1606
-        EE_Registry::$i18n_js_strings['confirm_delete'] = __('Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!', 'event_espresso');
1607
-        EE_Registry::$i18n_js_strings['January'] = __('January', 'event_espresso');
1608
-        EE_Registry::$i18n_js_strings['February'] = __('February', 'event_espresso');
1609
-        EE_Registry::$i18n_js_strings['March'] = __('March', 'event_espresso');
1610
-        EE_Registry::$i18n_js_strings['April'] = __('April', 'event_espresso');
1611
-        EE_Registry::$i18n_js_strings['May'] = __('May', 'event_espresso');
1612
-        EE_Registry::$i18n_js_strings['June'] = __('June', 'event_espresso');
1613
-        EE_Registry::$i18n_js_strings['July'] = __('July', 'event_espresso');
1614
-        EE_Registry::$i18n_js_strings['August'] = __('August', 'event_espresso');
1615
-        EE_Registry::$i18n_js_strings['September'] = __('September', 'event_espresso');
1616
-        EE_Registry::$i18n_js_strings['October'] = __('October', 'event_espresso');
1617
-        EE_Registry::$i18n_js_strings['November'] = __('November', 'event_espresso');
1618
-        EE_Registry::$i18n_js_strings['December'] = __('December', 'event_espresso');
1619
-        EE_Registry::$i18n_js_strings['Jan'] = __('Jan', 'event_espresso');
1620
-        EE_Registry::$i18n_js_strings['Feb'] = __('Feb', 'event_espresso');
1621
-        EE_Registry::$i18n_js_strings['Mar'] = __('Mar', 'event_espresso');
1622
-        EE_Registry::$i18n_js_strings['Apr'] = __('Apr', 'event_espresso');
1623
-        EE_Registry::$i18n_js_strings['May'] = __('May', 'event_espresso');
1624
-        EE_Registry::$i18n_js_strings['Jun'] = __('Jun', 'event_espresso');
1625
-        EE_Registry::$i18n_js_strings['Jul'] = __('Jul', 'event_espresso');
1626
-        EE_Registry::$i18n_js_strings['Aug'] = __('Aug', 'event_espresso');
1627
-        EE_Registry::$i18n_js_strings['Sep'] = __('Sep', 'event_espresso');
1628
-        EE_Registry::$i18n_js_strings['Oct'] = __('Oct', 'event_espresso');
1629
-        EE_Registry::$i18n_js_strings['Nov'] = __('Nov', 'event_espresso');
1630
-        EE_Registry::$i18n_js_strings['Dec'] = __('Dec', 'event_espresso');
1631
-        EE_Registry::$i18n_js_strings['Sunday'] = __('Sunday', 'event_espresso');
1632
-        EE_Registry::$i18n_js_strings['Monday'] = __('Monday', 'event_espresso');
1633
-        EE_Registry::$i18n_js_strings['Tuesday'] = __('Tuesday', 'event_espresso');
1634
-        EE_Registry::$i18n_js_strings['Wednesday'] = __('Wednesday', 'event_espresso');
1635
-        EE_Registry::$i18n_js_strings['Thursday'] = __('Thursday', 'event_espresso');
1636
-        EE_Registry::$i18n_js_strings['Friday'] = __('Friday', 'event_espresso');
1637
-        EE_Registry::$i18n_js_strings['Saturday'] = __('Saturday', 'event_espresso');
1638
-        EE_Registry::$i18n_js_strings['Sun'] = __('Sun', 'event_espresso');
1639
-        EE_Registry::$i18n_js_strings['Mon'] = __('Mon', 'event_espresso');
1640
-        EE_Registry::$i18n_js_strings['Tue'] = __('Tue', 'event_espresso');
1641
-        EE_Registry::$i18n_js_strings['Wed'] = __('Wed', 'event_espresso');
1642
-        EE_Registry::$i18n_js_strings['Thu'] = __('Thu', 'event_espresso');
1643
-        EE_Registry::$i18n_js_strings['Fri'] = __('Fri', 'event_espresso');
1644
-        EE_Registry::$i18n_js_strings['Sat'] = __('Sat', 'event_espresso');
1645
-    }
1646
-
1647
-
1648
-
1649
-    /**
1650
-     *        load enhanced xdebug styles for ppl with failing eyesight
1651
-     *
1652
-     * @access        public
1653
-     * @return        void
1654
-     */
1655
-    public function add_xdebug_style()
1656
-    {
1657
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1658
-    }
1659
-
1660
-
1661
-    /************************/
1662
-    /** LIST TABLE METHODS **/
1663
-    /************************/
1664
-    /**
1665
-     * this sets up the list table if the current view requires it.
1666
-     *
1667
-     * @access protected
1668
-     * @return void
1669
-     */
1670
-    protected function _set_list_table()
1671
-    {
1672
-        //first is this a list_table view?
1673
-        if ( ! isset($this->_route_config['list_table'])) {
1674
-            return;
1675
-        } //not a list_table view so get out.
1676
-        //list table functions are per view specific (because some admin pages might have more than one listtable!)
1677
-        if (call_user_func(array($this, '_set_list_table_views_' . $this->_req_action)) === false) {
1678
-            //user error msg
1679
-            $error_msg = __('An error occurred. The requested list table views could not be found.', 'event_espresso');
1680
-            //developer error msg
1681
-            $error_msg .= '||' . sprintf(__('List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.', 'event_espresso'),
1682
-                            $this->_req_action, '_set_list_table_views_' . $this->_req_action);
1683
-            throw new EE_Error($error_msg);
1684
-        }
1685
-        //let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
1686
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action, $this->_views);
1687
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
1688
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
1689
-        $this->_set_list_table_view();
1690
-        $this->_set_list_table_object();
1691
-    }
1692
-
1693
-
1694
-
1695
-    /**
1696
-     *        set current view for List Table
1697
-     *
1698
-     * @access public
1699
-     * @return array
1700
-     */
1701
-    protected function _set_list_table_view()
1702
-    {
1703
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1704
-        // looking at active items or dumpster diving ?
1705
-        if ( ! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
1706
-            $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
1707
-        } else {
1708
-            $this->_view = sanitize_key($this->_req_data['status']);
1709
-        }
1710
-    }
1711
-
1712
-
1713
-
1714
-    /**
1715
-     * _set_list_table_object
1716
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
1717
-     *
1718
-     * @throws \EE_Error
1719
-     */
1720
-    protected function _set_list_table_object()
1721
-    {
1722
-        if (isset($this->_route_config['list_table'])) {
1723
-            if ( ! class_exists($this->_route_config['list_table'])) {
1724
-                throw new EE_Error(
1725
-                        sprintf(
1726
-                                __(
1727
-                                        'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
1728
-                                        'event_espresso'
1729
-                                ),
1730
-                                $this->_route_config['list_table'],
1731
-                                get_class($this)
1732
-                        )
1733
-                );
1734
-            }
1735
-            $list_table = $this->_route_config['list_table'];
1736
-            $this->_list_table_object = new $list_table($this);
1737
-        }
1738
-    }
1739
-
1740
-
1741
-
1742
-    /**
1743
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
1744
-     *
1745
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
1746
-     *                                                    urls.  The array should be indexed by the view it is being
1747
-     *                                                    added to.
1748
-     * @return array
1749
-     */
1750
-    public function get_list_table_view_RLs($extra_query_args = array())
1751
-    {
1752
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1753
-        if (empty($this->_views)) {
1754
-            $this->_views = array();
1755
-        }
1756
-        // cycle thru views
1757
-        foreach ($this->_views as $key => $view) {
1758
-            $query_args = array();
1759
-            // check for current view
1760
-            $this->_views[$key]['class'] = $this->_view == $view['slug'] ? 'current' : '';
1761
-            $query_args['action'] = $this->_req_action;
1762
-            $query_args[$this->_req_action . '_nonce'] = wp_create_nonce($query_args['action'] . '_nonce');
1763
-            $query_args['status'] = $view['slug'];
1764
-            //merge any other arguments sent in.
1765
-            if (isset($extra_query_args[$view['slug']])) {
1766
-                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
1767
-            }
1768
-            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1769
-        }
1770
-        return $this->_views;
1771
-    }
1772
-
1773
-
1774
-
1775
-    /**
1776
-     * _entries_per_page_dropdown
1777
-     * generates a drop down box for selecting the number of visiable rows in an admin page list table
1778
-     *
1779
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how WP does it.
1780
-     * @access protected
1781
-     * @param int $max_entries total number of rows in the table
1782
-     * @return string
1783
-     */
1784
-    protected function _entries_per_page_dropdown($max_entries = false)
1785
-    {
1786
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1787
-        $values = array(10, 25, 50, 100);
1788
-        $per_page = ( ! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
1789
-        if ($max_entries) {
1790
-            $values[] = $max_entries;
1791
-            sort($values);
1792
-        }
1793
-        $entries_per_page_dropdown = '
145
+	// yes / no array for admin form fields
146
+	protected $_yes_no_values = array();
147
+
148
+	//some default things shared by all child classes
149
+	protected $_default_espresso_metaboxes;
150
+
151
+	/**
152
+	 *    EE_Registry Object
153
+	 *
154
+	 * @var    EE_Registry
155
+	 * @access    protected
156
+	 */
157
+	protected $EE = null;
158
+
159
+
160
+
161
+	/**
162
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
163
+	 *
164
+	 * @var boolean
165
+	 */
166
+	protected $_is_caf = false;
167
+
168
+
169
+
170
+	/**
171
+	 * @Constructor
172
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
173
+	 * @access public
174
+	 */
175
+	public function __construct($routing = true)
176
+	{
177
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
178
+			$this->_is_caf = true;
179
+		}
180
+		$this->_yes_no_values = array(
181
+				array('id' => true, 'text' => __('Yes', 'event_espresso')),
182
+				array('id' => false, 'text' => __('No', 'event_espresso')),
183
+		);
184
+		//set the _req_data property.
185
+		$this->_req_data = array_merge($_GET, $_POST);
186
+		//routing enabled?
187
+		$this->_routing = $routing;
188
+		//set initial page props (child method)
189
+		$this->_init_page_props();
190
+		//set global defaults
191
+		$this->_set_defaults();
192
+		//set early because incoming requests could be ajax related and we need to register those hooks.
193
+		$this->_global_ajax_hooks();
194
+		$this->_ajax_hooks();
195
+		//other_page_hooks have to be early too.
196
+		$this->_do_other_page_hooks();
197
+		//This just allows us to have extending classes do something specific
198
+		// before the parent constructor runs _page_setup().
199
+		if (method_exists($this, '_before_page_setup')) {
200
+			$this->_before_page_setup();
201
+		}
202
+		//set up page dependencies
203
+		$this->_page_setup();
204
+	}
205
+
206
+
207
+
208
+	/**
209
+	 * _init_page_props
210
+	 * Child classes use to set at least the following properties:
211
+	 * $page_slug.
212
+	 * $page_label.
213
+	 *
214
+	 * @abstract
215
+	 * @access protected
216
+	 * @return void
217
+	 */
218
+	abstract protected function _init_page_props();
219
+
220
+
221
+
222
+	/**
223
+	 * _ajax_hooks
224
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
225
+	 * Note: within the ajax callback methods.
226
+	 *
227
+	 * @abstract
228
+	 * @access protected
229
+	 * @return void
230
+	 */
231
+	abstract protected function _ajax_hooks();
232
+
233
+
234
+
235
+	/**
236
+	 * _define_page_props
237
+	 * child classes define page properties in here.  Must include at least:
238
+	 * $_admin_base_url = base_url for all admin pages
239
+	 * $_admin_page_title = default admin_page_title for admin pages
240
+	 * $_labels = array of default labels for various automatically generated elements:
241
+	 *    array(
242
+	 *        'buttons' => array(
243
+	 *            'add' => __('label for add new button'),
244
+	 *            'edit' => __('label for edit button'),
245
+	 *            'delete' => __('label for delete button')
246
+	 *            )
247
+	 *        )
248
+	 *
249
+	 * @abstract
250
+	 * @access protected
251
+	 * @return void
252
+	 */
253
+	abstract protected function _define_page_props();
254
+
255
+
256
+
257
+	/**
258
+	 * _set_page_routes
259
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also have a 'default'
260
+	 * route. Here's the format
261
+	 * $this->_page_routes = array(
262
+	 *        'default' => array(
263
+	 *            'func' => '_default_method_handling_route',
264
+	 *            'args' => array('array','of','args'),
265
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e. ajax request, backend processing)
266
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a headers route after.  The string you enter here should match the defined route reference for a headers sent route.
267
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access this route.
268
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability checks).
269
+	 *        ),
270
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a handling method.
271
+	 *        )
272
+	 * )
273
+	 *
274
+	 * @abstract
275
+	 * @access protected
276
+	 * @return void
277
+	 */
278
+	abstract protected function _set_page_routes();
279
+
280
+
281
+
282
+	/**
283
+	 * _set_page_config
284
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the array corresponds to the page_route for the loaded page.
285
+	 * Format:
286
+	 * $this->_page_config = array(
287
+	 *        'default' => array(
288
+	 *            'labels' => array(
289
+	 *                'buttons' => array(
290
+	 *                    'add' => __('label for adding item'),
291
+	 *                    'edit' => __('label for editing item'),
292
+	 *                    'delete' => __('label for deleting item')
293
+	 *                ),
294
+	 *                'publishbox' => __('Localized Title for Publish metabox', 'event_espresso')
295
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the page. If this isn't present then the defaults will be used as set for the $this->_labels in _define_page_props() method
296
+	 *            'nav' => array(
297
+	 *                'label' => __('Label for Tab', 'event_espresso').
298
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
299
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
300
+	 *                'order' => 10, //required to indicate tab position.
301
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is displayed then add this parameter.
302
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
303
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load metaboxes set for eventespresso admin pages.
304
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added later.  We just use
305
+	 *            this flag to make sure the necessary js gets enqueued on page load.
306
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
307
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The array indicates the max number of columns (4) and the default number of columns on page load (2).  There is an option
308
+	 *            in the "screen_options" dropdown that is setup so users can pick what columns they want to display.
309
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
310
+	 *                'tab_id' => array(
311
+	 *                    'title' => 'tab_title',
312
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting help tab content.  The fallback if it isn't present is to try a the callback.  Filename should match a file in the admin
313
+	 *                    folder's "help_tabs" dir (ie.. events/help_tabs/name_of_file_containing_content.help_tab.php)
314
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will attempt to use the callback which should match the name of a method in the class
315
+	 *                    ),
316
+	 *                'tab2_id' => array(
317
+	 *                    'title' => 'tab2 title',
318
+	 *                    'filename' => 'file_name_2'
319
+	 *                    'callback' => 'callback_method_for_content',
320
+	 *                 ),
321
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the help tab area on an admin page. @link http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
322
+	 *            'help_tour' => array(
323
+	 *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located in a folder for this admin page named "help_tours", a file name matching the key given here
324
+	 *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
325
+	 *            ),
326
+	 *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is true if it isn't present).  To remove the requirement for a nonce check when this route is visited just set
327
+	 *            'require_nonce' to FALSE
328
+	 *            )
329
+	 * )
330
+	 *
331
+	 * @abstract
332
+	 * @access protected
333
+	 * @return void
334
+	 */
335
+	abstract protected function _set_page_config();
336
+
337
+
338
+
339
+
340
+
341
+	/** end sample help_tour methods **/
342
+	/**
343
+	 * _add_screen_options
344
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
345
+	 * Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options to a particular view.
346
+	 *
347
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
348
+	 *         see also WP_Screen object documents...
349
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
350
+	 * @abstract
351
+	 * @access protected
352
+	 * @return void
353
+	 */
354
+	abstract protected function _add_screen_options();
355
+
356
+
357
+
358
+	/**
359
+	 * _add_feature_pointers
360
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
361
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a particular view.
362
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
363
+	 * See: WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be extended) also see:
364
+	 *
365
+	 * @link   http://eamann.com/tech/wordpress-portland/
366
+	 * @abstract
367
+	 * @access protected
368
+	 * @return void
369
+	 */
370
+	abstract protected function _add_feature_pointers();
371
+
372
+
373
+
374
+	/**
375
+	 * load_scripts_styles
376
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific scripts/styles
377
+	 * per view by putting them in a dynamic function in this format (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
378
+	 *
379
+	 * @abstract
380
+	 * @access public
381
+	 * @return void
382
+	 */
383
+	abstract public function load_scripts_styles();
384
+
385
+
386
+
387
+	/**
388
+	 * admin_init
389
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to all pages/views loaded by child class.
390
+	 *
391
+	 * @abstract
392
+	 * @access public
393
+	 * @return void
394
+	 */
395
+	abstract public function admin_init();
396
+
397
+
398
+
399
+	/**
400
+	 * admin_notices
401
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to all pages/views loaded by child class.
402
+	 *
403
+	 * @abstract
404
+	 * @access public
405
+	 * @return void
406
+	 */
407
+	abstract public function admin_notices();
408
+
409
+
410
+
411
+	/**
412
+	 * admin_footer_scripts
413
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method will apply to all pages/views loaded by child class.
414
+	 *
415
+	 * @access public
416
+	 * @return void
417
+	 */
418
+	abstract public function admin_footer_scripts();
419
+
420
+
421
+
422
+	/**
423
+	 * admin_footer
424
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will apply to all pages/views loaded by child class.
425
+	 *
426
+	 * @access  public
427
+	 * @return void
428
+	 */
429
+	public function admin_footer()
430
+	{
431
+	}
432
+
433
+
434
+
435
+	/**
436
+	 * _global_ajax_hooks
437
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
438
+	 * Note: within the ajax callback methods.
439
+	 *
440
+	 * @abstract
441
+	 * @access protected
442
+	 * @return void
443
+	 */
444
+	protected function _global_ajax_hooks()
445
+	{
446
+		//for lazy loading of metabox content
447
+		add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
448
+	}
449
+
450
+
451
+
452
+	public function ajax_metabox_content()
453
+	{
454
+		$contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
455
+		$url = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
456
+		self::cached_rss_display($contentid, $url);
457
+		wp_die();
458
+	}
459
+
460
+
461
+
462
+	/**
463
+	 * _page_setup
464
+	 * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested doesn't match the object.
465
+	 *
466
+	 * @final
467
+	 * @access protected
468
+	 * @return void
469
+	 */
470
+	final protected function _page_setup()
471
+	{
472
+		//requires?
473
+		//admin_init stuff - global - we're setting this REALLY early so if EE_Admin pages have to hook into other WP pages they can.  But keep in mind, not everything is available from the EE_Admin Page object at this point.
474
+		add_action('admin_init', array($this, 'admin_init_global'), 5);
475
+		//next verify if we need to load anything...
476
+		$this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
477
+		$this->page_folder = strtolower(str_replace('_Admin_Page', '', str_replace('Extend_', '', get_class($this))));
478
+		global $ee_menu_slugs;
479
+		$ee_menu_slugs = (array)$ee_menu_slugs;
480
+		if (( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page])) && ! defined('DOING_AJAX')) {
481
+			return;
482
+		}
483
+		// becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
484
+		if (isset($this->_req_data['action2']) && $this->_req_data['action'] == -1) {
485
+			$this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] != -1 ? $this->_req_data['action2'] : $this->_req_data['action'];
486
+		}
487
+		// then set blank or -1 action values to 'default'
488
+		$this->_req_action = isset($this->_req_data['action']) && ! empty($this->_req_data['action']) && $this->_req_data['action'] != -1 ? sanitize_key($this->_req_data['action']) : 'default';
489
+		//if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.  This covers cases where we're coming in from a list table that isn't on the default route.
490
+		$this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route']) ? $this->_req_data['route'] : $this->_req_action;
491
+		//however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
492
+		$this->_req_action = defined('DOING_AJAX') && isset($this->_req_data['route']) ? $this->_req_data['route'] : $this->_req_action;
493
+		$this->_current_view = $this->_req_action;
494
+		$this->_req_nonce = $this->_req_action . '_nonce';
495
+		$this->_define_page_props();
496
+		$this->_current_page_view_url = add_query_arg(array('page' => $this->_current_page, 'action' => $this->_current_view), $this->_admin_base_url);
497
+		//default things
498
+		$this->_default_espresso_metaboxes = array('_espresso_news_post_box', '_espresso_links_post_box', '_espresso_ratings_request', '_espresso_sponsors_post_box');
499
+		//set page configs
500
+		$this->_set_page_routes();
501
+		$this->_set_page_config();
502
+		//let's include any referrer data in our default_query_args for this route for "stickiness".
503
+		if (isset($this->_req_data['wp_referer'])) {
504
+			$this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
505
+		}
506
+		//for caffeinated and other extended functionality.  If there is a _extend_page_config method then let's run that to modify the all the various page configuration arrays
507
+		if (method_exists($this, '_extend_page_config')) {
508
+			$this->_extend_page_config();
509
+		}
510
+		//for CPT and other extended functionality. If there is an _extend_page_config_for_cpt then let's run that to modify all the various page configuration arrays.
511
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
512
+			$this->_extend_page_config_for_cpt();
513
+		}
514
+		//filter routes and page_config so addons can add their stuff. Filtering done per class
515
+		$this->_page_routes = apply_filters('FHEE__' . get_class($this) . '__page_setup__page_routes', $this->_page_routes, $this);
516
+		$this->_page_config = apply_filters('FHEE__' . get_class($this) . '__page_setup__page_config', $this->_page_config, $this);
517
+		//if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
518
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
519
+			add_action('AHEE__EE_Admin_Page__route_admin_request', array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view), 10, 2);
520
+		}
521
+		//next route only if routing enabled
522
+		if ($this->_routing && ! defined('DOING_AJAX')) {
523
+			$this->_verify_routes();
524
+			//next let's just check user_access and kill if no access
525
+			$this->check_user_access();
526
+			if ($this->_is_UI_request) {
527
+				//admin_init stuff - global, all views for this page class, specific view
528
+				add_action('admin_init', array($this, 'admin_init'), 10);
529
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
530
+					add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
531
+				}
532
+			} else {
533
+				//hijack regular WP loading and route admin request immediately
534
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
535
+				$this->route_admin_request();
536
+			}
537
+		}
538
+	}
539
+
540
+
541
+
542
+	/**
543
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
544
+	 *
545
+	 * @access private
546
+	 * @return void
547
+	 */
548
+	private function _do_other_page_hooks()
549
+	{
550
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
551
+		foreach ($registered_pages as $page) {
552
+			//now let's setup the file name and class that should be present
553
+			$classname = str_replace('.class.php', '', $page);
554
+			//autoloaders should take care of loading file
555
+			if ( ! class_exists($classname)) {
556
+				$error_msg[] = sprintf( esc_html__('Something went wrong with loading the %s admin hooks page.', 'event_espresso'), $page);
557
+				$error_msg[] = $error_msg[0]
558
+							   . "\r\n"
559
+							   . sprintf( esc_html__('There is no class in place for the %1$s admin hooks page.%2$sMake sure you have %3$s defined. If this is a non-EE-core admin page then you also must have an autoloader in place for your class',
560
+								'event_espresso'), $page, '<br />', '<strong>' . $classname . '</strong>');
561
+				throw new EE_Error(implode('||', $error_msg));
562
+			}
563
+			$a = new ReflectionClass($classname);
564
+			//notice we are passing the instance of this class to the hook object.
565
+			$hookobj[] = $a->newInstance($this);
566
+		}
567
+	}
568
+
569
+
570
+
571
+	public function load_page_dependencies()
572
+	{
573
+		try {
574
+			$this->_load_page_dependencies();
575
+		} catch (EE_Error $e) {
576
+			$e->get_error();
577
+		}
578
+	}
579
+
580
+
581
+
582
+	/**
583
+	 * load_page_dependencies
584
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
585
+	 *
586
+	 * @access public
587
+	 * @return void
588
+	 */
589
+	protected function _load_page_dependencies()
590
+	{
591
+		//let's set the current_screen and screen options to override what WP set
592
+		$this->_current_screen = get_current_screen();
593
+		//load admin_notices - global, page class, and view specific
594
+		add_action('admin_notices', array($this, 'admin_notices_global'), 5);
595
+		add_action('admin_notices', array($this, 'admin_notices'), 10);
596
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
597
+			add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
598
+		}
599
+		//load network admin_notices - global, page class, and view specific
600
+		add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
601
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
602
+			add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
603
+		}
604
+		//this will save any per_page screen options if they are present
605
+		$this->_set_per_page_screen_options();
606
+		//setup list table properties
607
+		$this->_set_list_table();
608
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.  However in some cases the metaboxes will need to be added within a route handling callback.
609
+		$this->_add_registered_meta_boxes();
610
+		$this->_add_screen_columns();
611
+		//add screen options - global, page child class, and view specific
612
+		$this->_add_global_screen_options();
613
+		$this->_add_screen_options();
614
+		if (method_exists($this, '_add_screen_options_' . $this->_current_view)) {
615
+			call_user_func(array($this, '_add_screen_options_' . $this->_current_view));
616
+		}
617
+		//add help tab(s) and tours- set via page_config and qtips.
618
+		$this->_add_help_tour();
619
+		$this->_add_help_tabs();
620
+		$this->_add_qtips();
621
+		//add feature_pointers - global, page child class, and view specific
622
+		$this->_add_feature_pointers();
623
+		$this->_add_global_feature_pointers();
624
+		if (method_exists($this, '_add_feature_pointer_' . $this->_current_view)) {
625
+			call_user_func(array($this, '_add_feature_pointer_' . $this->_current_view));
626
+		}
627
+		//enqueue scripts/styles - global, page class, and view specific
628
+		add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
629
+		add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
630
+		if (method_exists($this, 'load_scripts_styles_' . $this->_current_view)) {
631
+			add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles_' . $this->_current_view), 15);
632
+		}
633
+		add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
634
+		//admin_print_footer_scripts - global, page child class, and view specific.  NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.  In most cases that's doing_it_wrong().  But adding hidden container elements etc. is a good use case. Notice the late priority we're giving these
635
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
636
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
637
+		if (method_exists($this, 'admin_footer_scripts_' . $this->_current_view)) {
638
+			add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_' . $this->_current_view), 101);
639
+		}
640
+		//admin footer scripts
641
+		add_action('admin_footer', array($this, 'admin_footer_global'), 99);
642
+		add_action('admin_footer', array($this, 'admin_footer'), 100);
643
+		if (method_exists($this, 'admin_footer_' . $this->_current_view)) {
644
+			add_action('admin_footer', array($this, 'admin_footer_' . $this->_current_view), 101);
645
+		}
646
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
647
+		//targeted hook
648
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load__' . $this->page_slug . '__' . $this->_req_action);
649
+	}
650
+
651
+
652
+
653
+	/**
654
+	 * _set_defaults
655
+	 * This sets some global defaults for class properties.
656
+	 */
657
+	private function _set_defaults()
658
+	{
659
+		$this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = $this->_event = $this->_template_path = $this->_column_template_path = null;
660
+		$this->_nav_tabs = $this_views = $this->_page_routes = $this->_page_config = $this->_default_route_query_args = array();
661
+		$this->default_nav_tab_name = 'overview';
662
+		//init template args
663
+		$this->_template_args = array(
664
+				'admin_page_header'  => '',
665
+				'admin_page_content' => '',
666
+				'post_body_content'  => '',
667
+				'before_list_table'  => '',
668
+				'after_list_table'   => '',
669
+		);
670
+	}
671
+
672
+
673
+
674
+	/**
675
+	 * route_admin_request
676
+	 *
677
+	 * @see    _route_admin_request()
678
+	 * @access public
679
+	 * @return void|exception error
680
+	 */
681
+	public function route_admin_request()
682
+	{
683
+		try {
684
+			$this->_route_admin_request();
685
+		} catch (EE_Error $e) {
686
+			$e->get_error();
687
+		}
688
+	}
689
+
690
+
691
+
692
+	public function set_wp_page_slug($wp_page_slug)
693
+	{
694
+		$this->_wp_page_slug = $wp_page_slug;
695
+		//if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
696
+		if (is_network_admin()) {
697
+			$this->_wp_page_slug .= '-network';
698
+		}
699
+	}
700
+
701
+
702
+
703
+	/**
704
+	 * _verify_routes
705
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so we know if we need to drop out.
706
+	 *
707
+	 * @access protected
708
+	 * @return void
709
+	 */
710
+	protected function _verify_routes()
711
+	{
712
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
713
+		if ( ! $this->_current_page && ! defined('DOING_AJAX')) {
714
+			return false;
715
+		}
716
+		$this->_route = false;
717
+		$func = false;
718
+		$args = array();
719
+		// check that the page_routes array is not empty
720
+		if (empty($this->_page_routes)) {
721
+			// user error msg
722
+			$error_msg = sprintf(__('No page routes have been set for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
723
+			// developer error msg
724
+			$error_msg .= '||' . $error_msg . __(' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.', 'event_espresso');
725
+			throw new EE_Error($error_msg);
726
+		}
727
+		// and that the requested page route exists
728
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
729
+			$this->_route = $this->_page_routes[$this->_req_action];
730
+			$this->_route_config = isset($this->_page_config[$this->_req_action]) ? $this->_page_config[$this->_req_action] : array();
731
+		} else {
732
+			// user error msg
733
+			$error_msg = sprintf(__('The requested page route does not exist for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
734
+			// developer error msg
735
+			$error_msg .= '||' . $error_msg . sprintf(__(' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.', 'event_espresso'), $this->_req_action);
736
+			throw new EE_Error($error_msg);
737
+		}
738
+		// and that a default route exists
739
+		if ( ! array_key_exists('default', $this->_page_routes)) {
740
+			// user error msg
741
+			$error_msg = sprintf(__('A default page route has not been set for the % admin page.', 'event_espresso'), $this->_admin_page_title);
742
+			// developer error msg
743
+			$error_msg .= '||' . $error_msg . __(' Create a key in the "_page_routes" array named "default" and set its value to your default page method.', 'event_espresso');
744
+			throw new EE_Error($error_msg);
745
+		}
746
+		//first lets' catch if the UI request has EVER been set.
747
+		if ($this->_is_UI_request === null) {
748
+			//lets set if this is a UI request or not.
749
+			$this->_is_UI_request = ( ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true) ? true : false;
750
+			//wait a minute... we might have a noheader in the route array
751
+			$this->_is_UI_request = is_array($this->_route) && isset($this->_route['noheader']) && $this->_route['noheader'] ? false : $this->_is_UI_request;
752
+		}
753
+		$this->_set_current_labels();
754
+	}
755
+
756
+
757
+
758
+	/**
759
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
760
+	 *
761
+	 * @param  string $route the route name we're verifying
762
+	 * @return mixed  (bool|Exception)      we'll throw an exception if this isn't a valid route.
763
+	 */
764
+	protected function _verify_route($route)
765
+	{
766
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
767
+			return true;
768
+		} else {
769
+			// user error msg
770
+			$error_msg = sprintf(__('The given page route does not exist for the %s admin page.', 'event_espresso'), $this->_admin_page_title);
771
+			// developer error msg
772
+			$error_msg .= '||' . $error_msg . sprintf(__(' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property', 'event_espresso'), $route);
773
+			throw new EE_Error($error_msg);
774
+		}
775
+	}
776
+
777
+
778
+
779
+	/**
780
+	 * perform nonce verification
781
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces using this method (and save retyping!)
782
+	 *
783
+	 * @param  string $nonce     The nonce sent
784
+	 * @param  string $nonce_ref The nonce reference string (name0)
785
+	 * @return mixed (bool|die)
786
+	 */
787
+	protected function _verify_nonce($nonce, $nonce_ref)
788
+	{
789
+		// verify nonce against expected value
790
+		if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
791
+			// these are not the droids you are looking for !!!
792
+			$msg = sprintf(__('%sNonce Fail.%s', 'event_espresso'), '<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">', '</a>');
793
+			if (WP_DEBUG) {
794
+				$msg .= "\n  " . sprintf(__('In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!', 'event_espresso'), __CLASS__);
795
+			}
796
+			if ( ! defined('DOING_AJAX')) {
797
+				wp_die($msg);
798
+			} else {
799
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
800
+				$this->_return_json();
801
+			}
802
+		}
803
+	}
804
+
805
+
806
+
807
+	/**
808
+	 * _route_admin_request()
809
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if theres are
810
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
811
+	 * in the page routes and then will try to load the corresponding method.
812
+	 *
813
+	 * @access protected
814
+	 * @return void
815
+	 * @throws \EE_Error
816
+	 */
817
+	protected function _route_admin_request()
818
+	{
819
+		if ( ! $this->_is_UI_request) {
820
+			$this->_verify_routes();
821
+		}
822
+		$nonce_check = isset($this->_route_config['require_nonce'])
823
+			? $this->_route_config['require_nonce']
824
+			: true;
825
+		if ($this->_req_action !== 'default' && $nonce_check) {
826
+			// set nonce from post data
827
+			$nonce = isset($this->_req_data[$this->_req_nonce])
828
+				? sanitize_text_field($this->_req_data[$this->_req_nonce])
829
+				: '';
830
+			$this->_verify_nonce($nonce, $this->_req_nonce);
831
+		}
832
+		//set the nav_tabs array but ONLY if this is  UI_request
833
+		if ($this->_is_UI_request) {
834
+			$this->_set_nav_tabs();
835
+		}
836
+		// grab callback function
837
+		$func = is_array($this->_route) ? $this->_route['func'] : $this->_route;
838
+		// check if callback has args
839
+		$args = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
840
+		$error_msg = '';
841
+		// action right before calling route
842
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
843
+		if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
844
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
845
+		}
846
+		// right before calling the route, let's remove _wp_http_referer from the
847
+		// $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
848
+		$_SERVER['REQUEST_URI'] = remove_query_arg('_wp_http_referer', wp_unslash($_SERVER['REQUEST_URI']));
849
+		if ( ! empty($func)) {
850
+			if (is_array($func)) {
851
+				list($class, $method) = $func;
852
+			} else if (strpos($func, '::') !== false) {
853
+				list($class, $method) = explode('::', $func);
854
+			} else {
855
+				$class = $this;
856
+				$method = $func;
857
+			}
858
+			if ( ! (is_object($class) && $class === $this)) {
859
+				// send along this admin page object for access by addons.
860
+				$args['admin_page_object'] = $this;
861
+			}
862
+
863
+			if (
864
+				//is it a method on a class that doesn't work?
865
+				(
866
+					(
867
+						method_exists($class, $method)
868
+						&& call_user_func_array(array($class, $method), $args) === false
869
+					)
870
+					&& (
871
+						//is it a standalone function that doesn't work?
872
+						function_exists($method)
873
+						&& call_user_func_array($func, array_merge(array('admin_page_object' => $this), $args)) === false
874
+					)
875
+				)
876
+				|| (
877
+					//is it neither a class method NOR a standalone function?
878
+					! method_exists($class, $method)
879
+					&& ! function_exists($method)
880
+				)
881
+			) {
882
+				// user error msg
883
+				$error_msg = __('An error occurred. The  requested page route could not be found.', 'event_espresso');
884
+				// developer error msg
885
+				$error_msg .= '||';
886
+				$error_msg .= sprintf(
887
+					__(
888
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
889
+						'event_espresso'
890
+					),
891
+					$method
892
+				);
893
+			}
894
+			if ( ! empty($error_msg)) {
895
+				throw new EE_Error($error_msg);
896
+			}
897
+		}
898
+		//if we've routed and this route has a no headers route AND a sent_headers_route, then we need to reset the routing properties to the new route.
899
+		//now if UI request is FALSE and noheader is true AND we have a headers_sent_route in the route array then let's set UI_request to true because the no header route has a second func after headers have been sent.
900
+		if ($this->_is_UI_request === false
901
+			&& is_array($this->_route)
902
+			&& ! empty($this->_route['headers_sent_route'])
903
+		) {
904
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
905
+		}
906
+	}
907
+
908
+
909
+
910
+	/**
911
+	 * This method just allows the resetting of page properties in the case where a no headers
912
+	 * route redirects to a headers route in its route config.
913
+	 *
914
+	 * @since   4.3.0
915
+	 * @param  string $new_route New (non header) route to redirect to.
916
+	 * @return   void
917
+	 */
918
+	protected function _reset_routing_properties($new_route)
919
+	{
920
+		$this->_is_UI_request = true;
921
+		//now we set the current route to whatever the headers_sent_route is set at
922
+		$this->_req_data['action'] = $new_route;
923
+		//rerun page setup
924
+		$this->_page_setup();
925
+	}
926
+
927
+
928
+
929
+	/**
930
+	 * _add_query_arg
931
+	 * adds nonce to array of arguments then calls WP add_query_arg function
932
+	 *(internally just uses EEH_URL's function with the same name)
933
+	 *
934
+	 * @access public
935
+	 * @param array  $args
936
+	 * @param string $url
937
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the generated
938
+	 *                                        url in an associative array indexed by the key 'wp_referer';
939
+	 *                                        Example usage:
940
+	 *                                        If the current page is:
941
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
942
+	 *                                        &action=default&event_id=20&month_range=March%202015
943
+	 *                                        &_wpnonce=5467821
944
+	 *                                        and you call:
945
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
946
+	 *                                        array(
947
+	 *                                        'action' => 'resend_something',
948
+	 *                                        'page=>espresso_registrations'
949
+	 *                                        ),
950
+	 *                                        $some_url,
951
+	 *                                        true
952
+	 *                                        );
953
+	 *                                        It will produce a url in this structure:
954
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
955
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
956
+	 *                                        month_range]=March%202015
957
+	 * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
958
+	 * @return string
959
+	 */
960
+	public static function add_query_args_and_nonce($args = array(), $url = false, $sticky = false, $exclude_nonce = false)
961
+	{
962
+		//if there is a _wp_http_referer include the values from the request but only if sticky = true
963
+		if ($sticky) {
964
+			$request = $_REQUEST;
965
+			unset($request['_wp_http_referer']);
966
+			unset($request['wp_referer']);
967
+			foreach ($request as $key => $value) {
968
+				//do not add nonces
969
+				if (strpos($key, 'nonce') !== false) {
970
+					continue;
971
+				}
972
+				$args['wp_referer[' . $key . ']'] = $value;
973
+			}
974
+		}
975
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
976
+	}
977
+
978
+
979
+
980
+	/**
981
+	 * This returns a generated link that will load the related help tab.
982
+	 *
983
+	 * @param  string $help_tab_id the id for the connected help tab
984
+	 * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
985
+	 * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
986
+	 * @uses EEH_Template::get_help_tab_link()
987
+	 * @return string              generated link
988
+	 */
989
+	protected function _get_help_tab_link($help_tab_id, $icon_style = false, $help_text = false)
990
+	{
991
+		return EEH_Template::get_help_tab_link($help_tab_id, $this->page_slug, $this->_req_action, $icon_style, $help_text);
992
+	}
993
+
994
+
995
+
996
+	/**
997
+	 * _add_help_tabs
998
+	 * Note child classes define their help tabs within the page_config array.
999
+	 *
1000
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1001
+	 * @access protected
1002
+	 * @return void
1003
+	 */
1004
+	protected function _add_help_tabs()
1005
+	{
1006
+		$tour_buttons = '';
1007
+		if (isset($this->_page_config[$this->_req_action])) {
1008
+			$config = $this->_page_config[$this->_req_action];
1009
+			//is there a help tour for the current route?  if there is let's setup the tour buttons
1010
+			if (isset($this->_help_tour[$this->_req_action])) {
1011
+				$tb = array();
1012
+				$tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1013
+				foreach ($this->_help_tour['tours'] as $tour) {
1014
+					//if this is the end tour then we don't need to setup a button
1015
+					if ($tour instanceof EE_Help_Tour_final_stop) {
1016
+						continue;
1017
+					}
1018
+					$tb[] = '<button id="trigger-tour-' . $tour->get_slug() . '" class="button-primary trigger-ee-help-tour">' . $tour->get_label() . '</button>';
1019
+				}
1020
+				$tour_buttons .= implode('<br />', $tb);
1021
+				$tour_buttons .= '</div></div>';
1022
+			}
1023
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1024
+			if (is_array($config) && isset($config['help_sidebar'])) {
1025
+				//check that the callback given is valid
1026
+				if ( ! method_exists($this, $config['help_sidebar'])) {
1027
+					throw new EE_Error(sprintf(__('The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1028
+							'event_espresso'), $config['help_sidebar'], get_class($this)));
1029
+				}
1030
+				$content = apply_filters('FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar', call_user_func(array($this, $config['help_sidebar'])));
1031
+				$content .= $tour_buttons; //add help tour buttons.
1032
+				//do we have any help tours setup?  Cause if we do we want to add the buttons
1033
+				$this->_current_screen->set_help_sidebar($content);
1034
+			}
1035
+			//if we DON'T have config help sidebar and there ARE toure buttons then we'll just add the tour buttons to the sidebar.
1036
+			if ( ! isset($config['help_sidebar']) && ! empty($tour_buttons)) {
1037
+				$this->_current_screen->set_help_sidebar($tour_buttons);
1038
+			}
1039
+			//handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1040
+			if ( ! isset($config['help_tabs']) && ! empty($tour_buttons)) {
1041
+				$_ht['id'] = $this->page_slug;
1042
+				$_ht['title'] = __('Help Tours', 'event_espresso');
1043
+				$_ht['content'] = '<p>' . __('The buttons to the right allow you to start/restart any help tours available for this page', 'event_espresso') . '</p>';
1044
+				$this->_current_screen->add_help_tab($_ht);
1045
+			}/**/
1046
+			if ( ! isset($config['help_tabs'])) {
1047
+				return;
1048
+			} //no help tabs for this route
1049
+			foreach ((array)$config['help_tabs'] as $tab_id => $cfg) {
1050
+				//we're here so there ARE help tabs!
1051
+				//make sure we've got what we need
1052
+				if ( ! isset($cfg['title'])) {
1053
+					throw new EE_Error(__('The _page_config array is not set up properly for help tabs.  It is missing a title', 'event_espresso'));
1054
+				}
1055
+				if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1056
+					throw new EE_Error(__('The _page_config array is not setup properly for help tabs. It is missing a either a filename reference, or a callback reference or a content reference so there is no way to know the content for the help tab',
1057
+							'event_espresso'));
1058
+				}
1059
+				//first priority goes to content.
1060
+				if ( ! empty($cfg['content'])) {
1061
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1062
+					//second priority goes to filename
1063
+				} else if ( ! empty($cfg['filename'])) {
1064
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1065
+					//it's possible that the file is located on decaf route (and above sets up for caf route, if this is the case then lets check decaf route too)
1066
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES . basename($this->_get_dir()) . '/help_tabs/' . $cfg['filename'] . '.help_tab.php' : $file_path;
1067
+					//if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1068
+					if ( ! is_readable($file_path) && ! isset($cfg['callback'])) {
1069
+						EE_Error::add_error(sprintf(__('The filename given for the help tab %s is not a valid file and there is no other configuration for the tab content.  Please check that the string you set for the help tab on this route (%s) is the correct spelling.  The file should be in %s',
1070
+								'event_espresso'), $tab_id, key($config), $file_path), __FILE__, __FUNCTION__, __LINE__);
1071
+						return;
1072
+					}
1073
+					$template_args['admin_page_obj'] = $this;
1074
+					$content = EEH_Template::display_template($file_path, $template_args, true);
1075
+				} else {
1076
+					$content = '';
1077
+				}
1078
+				//check if callback is valid
1079
+				if (empty($content) && ( ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback']))) {
1080
+					EE_Error::add_error(sprintf(__('The callback given for a %s help tab on this page does not content OR a corresponding method for generating the content.  Check the spelling or make sure the method is present.',
1081
+							'event_espresso'), $cfg['title']), __FILE__, __FUNCTION__, __LINE__);
1082
+					return;
1083
+				}
1084
+				//setup config array for help tab method
1085
+				$id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1086
+				$_ht = array(
1087
+						'id'       => $id,
1088
+						'title'    => $cfg['title'],
1089
+						'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1090
+						'content'  => $content,
1091
+				);
1092
+				$this->_current_screen->add_help_tab($_ht);
1093
+			}
1094
+		}
1095
+	}
1096
+
1097
+
1098
+
1099
+	/**
1100
+	 * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is an array with properties for setting up usage of the joyride plugin
1101
+	 *
1102
+	 * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1103
+	 * @see    instructions regarding the format and construction of the "help_tour" array element is found in the _set_page_config() comments
1104
+	 * @access protected
1105
+	 * @return void
1106
+	 */
1107
+	protected function _add_help_tour()
1108
+	{
1109
+		$tours = array();
1110
+		$this->_help_tour = array();
1111
+		//exit early if help tours are turned off globally
1112
+		if ( ! EE_Registry::instance()->CFG->admin->help_tour_activation || (defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)) {
1113
+			return;
1114
+		}
1115
+		//loop through _page_config to find any help_tour defined
1116
+		foreach ($this->_page_config as $route => $config) {
1117
+			//we're only going to set things up for this route
1118
+			if ($route !== $this->_req_action) {
1119
+				continue;
1120
+			}
1121
+			if (isset($config['help_tour'])) {
1122
+				foreach ($config['help_tour'] as $tour) {
1123
+					$file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1124
+					//let's see if we can get that file... if not its possible this is a decaf route not set in caffienated so lets try and get the caffeinated equivalent
1125
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES . basename($this->_get_dir()) . '/help_tours/' . $tour . '.class.php' : $file_path;
1126
+					//if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1127
+					if ( ! is_readable($file_path)) {
1128
+						EE_Error::add_error(sprintf(__('The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling', 'event_espresso'),
1129
+								$file_path, $tour), __FILE__, __FUNCTION__, __LINE__);
1130
+						return;
1131
+					}
1132
+					require_once $file_path;
1133
+					if ( ! class_exists($tour)) {
1134
+						$error_msg[] = sprintf(__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'), $tour);
1135
+						$error_msg[] = $error_msg[0] . "\r\n" . sprintf(__('There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1136
+										'event_espresso'), $tour, '<br />', $tour, $this->_req_action, get_class($this));
1137
+						throw new EE_Error(implode('||', $error_msg));
1138
+					}
1139
+					$a = new ReflectionClass($tour);
1140
+					$tour_obj = $a->newInstance($this->_is_caf);
1141
+					$tours[] = $tour_obj;
1142
+					$this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($tour_obj);
1143
+				}
1144
+				//let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1145
+				$end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1146
+				$tours[] = $end_stop_tour;
1147
+				$this->_help_tour[$route][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1148
+			}
1149
+		}
1150
+		if ( ! empty($tours)) {
1151
+			$this->_help_tour['tours'] = $tours;
1152
+		}
1153
+		//thats it!  Now that the $_help_tours property is set (or not) the scripts and html should be taken care of automatically.
1154
+	}
1155
+
1156
+
1157
+
1158
+	/**
1159
+	 * This simply sets up any qtips that have been defined in the page config
1160
+	 *
1161
+	 * @access protected
1162
+	 * @return void
1163
+	 */
1164
+	protected function _add_qtips()
1165
+	{
1166
+		if (isset($this->_route_config['qtips'])) {
1167
+			$qtips = (array)$this->_route_config['qtips'];
1168
+			//load qtip loader
1169
+			$path = array(
1170
+					$this->_get_dir() . '/qtips/',
1171
+					EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1172
+			);
1173
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1174
+		}
1175
+	}
1176
+
1177
+
1178
+
1179
+	/**
1180
+	 * _set_nav_tabs
1181
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you wish to add additional tabs or modify accordingly.
1182
+	 *
1183
+	 * @access protected
1184
+	 * @return void
1185
+	 */
1186
+	protected function _set_nav_tabs()
1187
+	{
1188
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1189
+		$i = 0;
1190
+		foreach ($this->_page_config as $slug => $config) {
1191
+			if ( ! is_array($config) || (is_array($config) && (isset($config['nav']) && ! $config['nav']) || ! isset($config['nav']))) {
1192
+				continue;
1193
+			} //no nav tab for this config
1194
+			//check for persistent flag
1195
+			if (isset($config['nav']['persistent']) && ! $config['nav']['persistent'] && $slug !== $this->_req_action) {
1196
+				continue;
1197
+			} //nav tab is only to appear when route requested.
1198
+			if ( ! $this->check_user_access($slug, true)) {
1199
+				continue;
1200
+			} //no nav tab becasue current user does not have access.
1201
+			$css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1202
+			$this->_nav_tabs[$slug] = array(
1203
+					'url'       => isset($config['nav']['url']) ? $config['nav']['url'] : self::add_query_args_and_nonce(array('action' => $slug), $this->_admin_base_url),
1204
+					'link_text' => isset($config['nav']['label']) ? $config['nav']['label'] : ucwords(str_replace('_', ' ', $slug)),
1205
+					'css_class' => $this->_req_action == $slug ? $css_class . 'nav-tab-active' : $css_class,
1206
+					'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1207
+			);
1208
+			$i++;
1209
+		}
1210
+		//if $this->_nav_tabs is empty then lets set the default
1211
+		if (empty($this->_nav_tabs)) {
1212
+			$this->_nav_tabs[$this->default_nav_tab_name] = array(
1213
+					'url'       => $this->admin_base_url,
1214
+					'link_text' => ucwords(str_replace('_', ' ', $this->default_nav_tab_name)),
1215
+					'css_class' => 'nav-tab-active',
1216
+					'order'     => 10,
1217
+			);
1218
+		}
1219
+		//now let's sort the tabs according to order
1220
+		usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1221
+	}
1222
+
1223
+
1224
+
1225
+	/**
1226
+	 * _set_current_labels
1227
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes property array
1228
+	 *
1229
+	 * @access private
1230
+	 * @return void
1231
+	 */
1232
+	private function _set_current_labels()
1233
+	{
1234
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1235
+			foreach ($this->_route_config['labels'] as $label => $text) {
1236
+				if (is_array($text)) {
1237
+					foreach ($text as $sublabel => $subtext) {
1238
+						$this->_labels[$label][$sublabel] = $subtext;
1239
+					}
1240
+				} else {
1241
+					$this->_labels[$label] = $text;
1242
+				}
1243
+			}
1244
+		}
1245
+	}
1246
+
1247
+
1248
+
1249
+	/**
1250
+	 *        verifies user access for this admin page
1251
+	 *
1252
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1253
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just return false if verify fail.
1254
+	 * @return        BOOL|wp_die()
1255
+	 */
1256
+	public function check_user_access($route_to_check = '', $verify_only = false)
1257
+	{
1258
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1259
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1260
+		$capability = ! empty($route_to_check) && isset($this->_page_routes[$route_to_check]) && is_array($this->_page_routes[$route_to_check]) && ! empty($this->_page_routes[$route_to_check]['capability'])
1261
+				? $this->_page_routes[$route_to_check]['capability'] : null;
1262
+		if (empty($capability) && empty($route_to_check)) {
1263
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options' : $this->_route['capability'];
1264
+		} else {
1265
+			$capability = empty($capability) ? 'manage_options' : $capability;
1266
+		}
1267
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1268
+		if (( ! function_exists('is_admin') || ! EE_Registry::instance()->CAP->current_user_can($capability, $this->page_slug . '_' . $route_to_check, $id)) && ! defined('DOING_AJAX')) {
1269
+			if ($verify_only) {
1270
+				return false;
1271
+			} else {
1272
+				if ( is_user_logged_in() ) {
1273
+					wp_die(__('You do not have access to this route.', 'event_espresso'));
1274
+				} else {
1275
+					return false;
1276
+				}
1277
+			}
1278
+		}
1279
+		return true;
1280
+	}
1281
+
1282
+
1283
+
1284
+	/**
1285
+	 * admin_init_global
1286
+	 * This runs all the code that we want executed within the WP admin_init hook.
1287
+	 * This method executes for ALL EE Admin pages.
1288
+	 *
1289
+	 * @access public
1290
+	 * @return void
1291
+	 */
1292
+	public function admin_init_global()
1293
+	{
1294
+	}
1295
+
1296
+
1297
+
1298
+	/**
1299
+	 * wp_loaded_global
1300
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an EE_Admin page and will execute on every EE Admin Page load
1301
+	 *
1302
+	 * @access public
1303
+	 * @return void
1304
+	 */
1305
+	public function wp_loaded()
1306
+	{
1307
+	}
1308
+
1309
+
1310
+
1311
+	/**
1312
+	 * admin_notices
1313
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on ALL EE_Admin pages.
1314
+	 *
1315
+	 * @access public
1316
+	 * @return void
1317
+	 */
1318
+	public function admin_notices_global()
1319
+	{
1320
+		$this->_display_no_javascript_warning();
1321
+		$this->_display_espresso_notices();
1322
+	}
1323
+
1324
+
1325
+
1326
+	public function network_admin_notices_global()
1327
+	{
1328
+		$this->_display_no_javascript_warning();
1329
+		$this->_display_espresso_notices();
1330
+	}
1331
+
1332
+
1333
+
1334
+	/**
1335
+	 * admin_footer_scripts_global
1336
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method will apply on ALL EE_Admin pages.
1337
+	 *
1338
+	 * @access public
1339
+	 * @return void
1340
+	 */
1341
+	public function admin_footer_scripts_global()
1342
+	{
1343
+		$this->_add_admin_page_ajax_loading_img();
1344
+		$this->_add_admin_page_overlay();
1345
+		//if metaboxes are present we need to add the nonce field
1346
+		if ((isset($this->_route_config['metaboxes']) || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes']) || isset($this->_route_config['list_table']))) {
1347
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1348
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1349
+		}
1350
+	}
1351
+
1352
+
1353
+
1354
+	/**
1355
+	 * admin_footer_global
1356
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here. This particluar method will apply on ALL EE_Admin Pages.
1357
+	 *
1358
+	 * @access  public
1359
+	 * @return  void
1360
+	 */
1361
+	public function admin_footer_global()
1362
+	{
1363
+		//dialog container for dialog helper
1364
+		$d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1365
+		$d_cont .= '<div class="ee-notices"></div>';
1366
+		$d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1367
+		$d_cont .= '</div>';
1368
+		echo $d_cont;
1369
+		//help tour stuff?
1370
+		if (isset($this->_help_tour[$this->_req_action])) {
1371
+			echo implode('<br />', $this->_help_tour[$this->_req_action]);
1372
+		}
1373
+		//current set timezone for timezone js
1374
+		echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1375
+	}
1376
+
1377
+
1378
+
1379
+	/**
1380
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then we'll use the retrieved array to output the content using the template.
1381
+	 * For child classes:
1382
+	 * If you want to have help popups then in your templates or your content you set "triggers" for the content using the "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method for
1383
+	 * the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content for the
1384
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1385
+	 *    'help_trigger_id' => array(
1386
+	 *        'title' => __('localized title for popup', 'event_espresso'),
1387
+	 *        'content' => __('localized content for popup', 'event_espresso')
1388
+	 *    )
1389
+	 * );
1390
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1391
+	 *
1392
+	 * @access protected
1393
+	 * @return string content
1394
+	 */
1395
+	protected function _set_help_popup_content($help_array = array(), $display = false)
1396
+	{
1397
+		$content = '';
1398
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1399
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php';
1400
+		//loop through the array and setup content
1401
+		foreach ($help_array as $trigger => $help) {
1402
+			//make sure the array is setup properly
1403
+			if ( ! isset($help['title']) || ! isset($help['content'])) {
1404
+				throw new EE_Error(__('Does not look like the popup content array has been setup correctly.  Might want to double check that.  Read the comments for the _get_help_popup_content method found in "EE_Admin_Page" class',
1405
+						'event_espresso'));
1406
+			}
1407
+			//we're good so let'd setup the template vars and then assign parsed template content to our content.
1408
+			$template_args = array(
1409
+					'help_popup_id'      => $trigger,
1410
+					'help_popup_title'   => $help['title'],
1411
+					'help_popup_content' => $help['content'],
1412
+			);
1413
+			$content .= EEH_Template::display_template($template_path, $template_args, true);
1414
+		}
1415
+		if ($display) {
1416
+			echo $content;
1417
+		} else {
1418
+			return $content;
1419
+		}
1420
+	}
1421
+
1422
+
1423
+
1424
+	/**
1425
+	 * All this does is retrive the help content array if set by the EE_Admin_Page child
1426
+	 *
1427
+	 * @access private
1428
+	 * @return array properly formatted array for help popup content
1429
+	 */
1430
+	private function _get_help_content()
1431
+	{
1432
+		//what is the method we're looking for?
1433
+		$method_name = '_help_popup_content_' . $this->_req_action;
1434
+		//if method doesn't exist let's get out.
1435
+		if ( ! method_exists($this, $method_name)) {
1436
+			return array();
1437
+		}
1438
+		//k we're good to go let's retrieve the help array
1439
+		$help_array = call_user_func(array($this, $method_name));
1440
+		//make sure we've got an array!
1441
+		if ( ! is_array($help_array)) {
1442
+			throw new EE_Error(__('Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.', 'event_espresso'));
1443
+		}
1444
+		return $help_array;
1445
+	}
1446
+
1447
+
1448
+
1449
+	/**
1450
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1451
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1452
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1453
+	 *
1454
+	 * @access protected
1455
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1456
+	 * @param boolean $display    if false then we return the trigger string
1457
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1458
+	 * @return string
1459
+	 */
1460
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1461
+	{
1462
+		if (defined('DOING_AJAX')) {
1463
+			return;
1464
+		}
1465
+		//let's check and see if there is any content set for this popup.  If there isn't then we'll include a default title and content so that developers know something needs to be corrected
1466
+		$help_array = $this->_get_help_content();
1467
+		$help_content = '';
1468
+		if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1469
+			$help_array[$trigger_id] = array(
1470
+					'title'   => __('Missing Content', 'event_espresso'),
1471
+					'content' => __('A trigger has been set that doesn\'t have any corresponding content. Make sure you have set the help content. (see the "_set_help_popup_content" method in the EE_Admin_Page for instructions.)',
1472
+							'event_espresso'),
1473
+			);
1474
+			$help_content = $this->_set_help_popup_content($help_array, false);
1475
+		}
1476
+		//let's setup the trigger
1477
+		$content = '<a class="ee-dialog" href="?height=' . $dimensions[0] . '&width=' . $dimensions[1] . '&inlineId=' . $trigger_id . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1478
+		$content = $content . $help_content;
1479
+		if ($display) {
1480
+			echo $content;
1481
+		} else {
1482
+			return $content;
1483
+		}
1484
+	}
1485
+
1486
+
1487
+
1488
+	/**
1489
+	 * _add_global_screen_options
1490
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1491
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1492
+	 *
1493
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1494
+	 *         see also WP_Screen object documents...
1495
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1496
+	 * @abstract
1497
+	 * @access private
1498
+	 * @return void
1499
+	 */
1500
+	private function _add_global_screen_options()
1501
+	{
1502
+	}
1503
+
1504
+
1505
+
1506
+	/**
1507
+	 * _add_global_feature_pointers
1508
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1509
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1510
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1511
+	 *
1512
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be extended) also see:
1513
+	 * @link   http://eamann.com/tech/wordpress-portland/
1514
+	 * @abstract
1515
+	 * @access protected
1516
+	 * @return void
1517
+	 */
1518
+	private function _add_global_feature_pointers()
1519
+	{
1520
+	}
1521
+
1522
+
1523
+
1524
+	/**
1525
+	 * load_global_scripts_styles
1526
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1527
+	 *
1528
+	 * @return void
1529
+	 */
1530
+	public function load_global_scripts_styles()
1531
+	{
1532
+		/** STYLES **/
1533
+		// add debugging styles
1534
+		if (WP_DEBUG) {
1535
+			add_action('admin_head', array($this, 'add_xdebug_style'));
1536
+		}
1537
+		// register all styles
1538
+		wp_register_style('espresso-ui-theme', EE_GLOBAL_ASSETS_URL . 'css/espresso-ui-theme/jquery-ui-1.10.3.custom.min.css', array(), EVENT_ESPRESSO_VERSION);
1539
+		wp_register_style('ee-admin-css', EE_ADMIN_URL . 'assets/ee-admin-page.css', array(), EVENT_ESPRESSO_VERSION);
1540
+		//helpers styles
1541
+		wp_register_style('ee-text-links', EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.css', array(), EVENT_ESPRESSO_VERSION);
1542
+		/** SCRIPTS **/
1543
+		//register all scripts
1544
+		wp_register_script('ee-dialog', EE_ADMIN_URL . 'assets/ee-dialog-helper.js', array('jquery', 'jquery-ui-draggable'), EVENT_ESPRESSO_VERSION, true);
1545
+		wp_register_script('ee_admin_js', EE_ADMIN_URL . 'assets/ee-admin-page.js', array('espresso_core', 'ee-parse-uri', 'ee-dialog'), EVENT_ESPRESSO_VERSION, true);
1546
+		wp_register_script('jquery-ui-timepicker-addon', EE_GLOBAL_ASSETS_URL . 'scripts/jquery-ui-timepicker-addon.js', array('jquery-ui-datepicker', 'jquery-ui-slider'), EVENT_ESPRESSO_VERSION, true);
1547
+		add_filter('FHEE_load_joyride', '__return_true');
1548
+		//script for sorting tables
1549
+		wp_register_script('espresso_ajax_table_sorting', EE_ADMIN_URL . "assets/espresso_ajax_table_sorting.js", array('ee_admin_js', 'jquery-ui-sortable'), EVENT_ESPRESSO_VERSION, true);
1550
+		//script for parsing uri's
1551
+		wp_register_script('ee-parse-uri', EE_GLOBAL_ASSETS_URL . 'scripts/parseuri.js', array(), EVENT_ESPRESSO_VERSION, true);
1552
+		//and parsing associative serialized form elements
1553
+		wp_register_script('ee-serialize-full-array', EE_GLOBAL_ASSETS_URL . 'scripts/jquery.serializefullarray.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1554
+		//helpers scripts
1555
+		wp_register_script('ee-text-links', EE_PLUGIN_DIR_URL . 'core/helpers/assets/ee_text_list_helper.js', array('jquery'), EVENT_ESPRESSO_VERSION, true);
1556
+		wp_register_script('ee-moment-core', EE_THIRD_PARTY_URL . 'moment/moment-with-locales.min.js', array(), EVENT_ESPRESSO_VERSION, true);
1557
+		wp_register_script('ee-moment', EE_THIRD_PARTY_URL . 'moment/moment-timezone-with-data.min.js', array('ee-moment-core'), EVENT_ESPRESSO_VERSION, true);
1558
+		wp_register_script('ee-datepicker', EE_ADMIN_URL . 'assets/ee-datepicker.js', array('jquery-ui-timepicker-addon', 'ee-moment'), EVENT_ESPRESSO_VERSION, true);
1559
+		//google charts
1560
+		wp_register_script('google-charts', 'https://www.gstatic.com/charts/loader.js', array(), EVENT_ESPRESSO_VERSION, false);
1561
+		// ENQUEUE ALL BASICS BY DEFAULT
1562
+		wp_enqueue_style('ee-admin-css');
1563
+		wp_enqueue_script('ee_admin_js');
1564
+		wp_enqueue_script('ee-accounting');
1565
+		wp_enqueue_script('jquery-validate');
1566
+		//taking care of metaboxes
1567
+		if (
1568
+			empty($this->_cpt_route)
1569
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1570
+		) {
1571
+			wp_enqueue_script('dashboard');
1572
+		}
1573
+		// LOCALIZED DATA
1574
+		//localize script for ajax lazy loading
1575
+		$lazy_loader_container_ids = apply_filters('FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers', array('espresso_news_post_box_content'));
1576
+		wp_localize_script('ee_admin_js', 'eeLazyLoadingContainers', $lazy_loader_container_ids);
1577
+		/**
1578
+		 * help tour stuff
1579
+		 */
1580
+		if ( ! empty($this->_help_tour)) {
1581
+			//register the js for kicking things off
1582
+			wp_enqueue_script('ee-help-tour', EE_ADMIN_URL . 'assets/ee-help-tour.js', array('jquery-joyride'), EVENT_ESPRESSO_VERSION, true);
1583
+			//setup tours for the js tour object
1584
+			foreach ($this->_help_tour['tours'] as $tour) {
1585
+				$tours[] = array(
1586
+						'id'      => $tour->get_slug(),
1587
+						'options' => $tour->get_options(),
1588
+				);
1589
+			}
1590
+			wp_localize_script('ee-help-tour', 'EE_HELP_TOUR', array('tours' => $tours));
1591
+			//admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
1592
+		}
1593
+	}
1594
+
1595
+
1596
+
1597
+	/**
1598
+	 *        admin_footer_scripts_eei18n_js_strings
1599
+	 *
1600
+	 * @access        public
1601
+	 * @return        void
1602
+	 */
1603
+	public function admin_footer_scripts_eei18n_js_strings()
1604
+	{
1605
+		EE_Registry::$i18n_js_strings['ajax_url'] = WP_AJAX_URL;
1606
+		EE_Registry::$i18n_js_strings['confirm_delete'] = __('Are you absolutely sure you want to delete this item?\nThis action will delete ALL DATA associated with this item!!!\nThis can NOT be undone!!!', 'event_espresso');
1607
+		EE_Registry::$i18n_js_strings['January'] = __('January', 'event_espresso');
1608
+		EE_Registry::$i18n_js_strings['February'] = __('February', 'event_espresso');
1609
+		EE_Registry::$i18n_js_strings['March'] = __('March', 'event_espresso');
1610
+		EE_Registry::$i18n_js_strings['April'] = __('April', 'event_espresso');
1611
+		EE_Registry::$i18n_js_strings['May'] = __('May', 'event_espresso');
1612
+		EE_Registry::$i18n_js_strings['June'] = __('June', 'event_espresso');
1613
+		EE_Registry::$i18n_js_strings['July'] = __('July', 'event_espresso');
1614
+		EE_Registry::$i18n_js_strings['August'] = __('August', 'event_espresso');
1615
+		EE_Registry::$i18n_js_strings['September'] = __('September', 'event_espresso');
1616
+		EE_Registry::$i18n_js_strings['October'] = __('October', 'event_espresso');
1617
+		EE_Registry::$i18n_js_strings['November'] = __('November', 'event_espresso');
1618
+		EE_Registry::$i18n_js_strings['December'] = __('December', 'event_espresso');
1619
+		EE_Registry::$i18n_js_strings['Jan'] = __('Jan', 'event_espresso');
1620
+		EE_Registry::$i18n_js_strings['Feb'] = __('Feb', 'event_espresso');
1621
+		EE_Registry::$i18n_js_strings['Mar'] = __('Mar', 'event_espresso');
1622
+		EE_Registry::$i18n_js_strings['Apr'] = __('Apr', 'event_espresso');
1623
+		EE_Registry::$i18n_js_strings['May'] = __('May', 'event_espresso');
1624
+		EE_Registry::$i18n_js_strings['Jun'] = __('Jun', 'event_espresso');
1625
+		EE_Registry::$i18n_js_strings['Jul'] = __('Jul', 'event_espresso');
1626
+		EE_Registry::$i18n_js_strings['Aug'] = __('Aug', 'event_espresso');
1627
+		EE_Registry::$i18n_js_strings['Sep'] = __('Sep', 'event_espresso');
1628
+		EE_Registry::$i18n_js_strings['Oct'] = __('Oct', 'event_espresso');
1629
+		EE_Registry::$i18n_js_strings['Nov'] = __('Nov', 'event_espresso');
1630
+		EE_Registry::$i18n_js_strings['Dec'] = __('Dec', 'event_espresso');
1631
+		EE_Registry::$i18n_js_strings['Sunday'] = __('Sunday', 'event_espresso');
1632
+		EE_Registry::$i18n_js_strings['Monday'] = __('Monday', 'event_espresso');
1633
+		EE_Registry::$i18n_js_strings['Tuesday'] = __('Tuesday', 'event_espresso');
1634
+		EE_Registry::$i18n_js_strings['Wednesday'] = __('Wednesday', 'event_espresso');
1635
+		EE_Registry::$i18n_js_strings['Thursday'] = __('Thursday', 'event_espresso');
1636
+		EE_Registry::$i18n_js_strings['Friday'] = __('Friday', 'event_espresso');
1637
+		EE_Registry::$i18n_js_strings['Saturday'] = __('Saturday', 'event_espresso');
1638
+		EE_Registry::$i18n_js_strings['Sun'] = __('Sun', 'event_espresso');
1639
+		EE_Registry::$i18n_js_strings['Mon'] = __('Mon', 'event_espresso');
1640
+		EE_Registry::$i18n_js_strings['Tue'] = __('Tue', 'event_espresso');
1641
+		EE_Registry::$i18n_js_strings['Wed'] = __('Wed', 'event_espresso');
1642
+		EE_Registry::$i18n_js_strings['Thu'] = __('Thu', 'event_espresso');
1643
+		EE_Registry::$i18n_js_strings['Fri'] = __('Fri', 'event_espresso');
1644
+		EE_Registry::$i18n_js_strings['Sat'] = __('Sat', 'event_espresso');
1645
+	}
1646
+
1647
+
1648
+
1649
+	/**
1650
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1651
+	 *
1652
+	 * @access        public
1653
+	 * @return        void
1654
+	 */
1655
+	public function add_xdebug_style()
1656
+	{
1657
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1658
+	}
1659
+
1660
+
1661
+	/************************/
1662
+	/** LIST TABLE METHODS **/
1663
+	/************************/
1664
+	/**
1665
+	 * this sets up the list table if the current view requires it.
1666
+	 *
1667
+	 * @access protected
1668
+	 * @return void
1669
+	 */
1670
+	protected function _set_list_table()
1671
+	{
1672
+		//first is this a list_table view?
1673
+		if ( ! isset($this->_route_config['list_table'])) {
1674
+			return;
1675
+		} //not a list_table view so get out.
1676
+		//list table functions are per view specific (because some admin pages might have more than one listtable!)
1677
+		if (call_user_func(array($this, '_set_list_table_views_' . $this->_req_action)) === false) {
1678
+			//user error msg
1679
+			$error_msg = __('An error occurred. The requested list table views could not be found.', 'event_espresso');
1680
+			//developer error msg
1681
+			$error_msg .= '||' . sprintf(__('List table views for "%s" route could not be setup. Check that you have the corresponding method, "%s" set up for defining list_table_views for this route.', 'event_espresso'),
1682
+							$this->_req_action, '_set_list_table_views_' . $this->_req_action);
1683
+			throw new EE_Error($error_msg);
1684
+		}
1685
+		//let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
1686
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action, $this->_views);
1687
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
1688
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
1689
+		$this->_set_list_table_view();
1690
+		$this->_set_list_table_object();
1691
+	}
1692
+
1693
+
1694
+
1695
+	/**
1696
+	 *        set current view for List Table
1697
+	 *
1698
+	 * @access public
1699
+	 * @return array
1700
+	 */
1701
+	protected function _set_list_table_view()
1702
+	{
1703
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1704
+		// looking at active items or dumpster diving ?
1705
+		if ( ! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
1706
+			$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
1707
+		} else {
1708
+			$this->_view = sanitize_key($this->_req_data['status']);
1709
+		}
1710
+	}
1711
+
1712
+
1713
+
1714
+	/**
1715
+	 * _set_list_table_object
1716
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
1717
+	 *
1718
+	 * @throws \EE_Error
1719
+	 */
1720
+	protected function _set_list_table_object()
1721
+	{
1722
+		if (isset($this->_route_config['list_table'])) {
1723
+			if ( ! class_exists($this->_route_config['list_table'])) {
1724
+				throw new EE_Error(
1725
+						sprintf(
1726
+								__(
1727
+										'The %s class defined for the list table does not exist.  Please check the spelling of the class ref in the $_page_config property on %s.',
1728
+										'event_espresso'
1729
+								),
1730
+								$this->_route_config['list_table'],
1731
+								get_class($this)
1732
+						)
1733
+				);
1734
+			}
1735
+			$list_table = $this->_route_config['list_table'];
1736
+			$this->_list_table_object = new $list_table($this);
1737
+		}
1738
+	}
1739
+
1740
+
1741
+
1742
+	/**
1743
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
1744
+	 *
1745
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
1746
+	 *                                                    urls.  The array should be indexed by the view it is being
1747
+	 *                                                    added to.
1748
+	 * @return array
1749
+	 */
1750
+	public function get_list_table_view_RLs($extra_query_args = array())
1751
+	{
1752
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1753
+		if (empty($this->_views)) {
1754
+			$this->_views = array();
1755
+		}
1756
+		// cycle thru views
1757
+		foreach ($this->_views as $key => $view) {
1758
+			$query_args = array();
1759
+			// check for current view
1760
+			$this->_views[$key]['class'] = $this->_view == $view['slug'] ? 'current' : '';
1761
+			$query_args['action'] = $this->_req_action;
1762
+			$query_args[$this->_req_action . '_nonce'] = wp_create_nonce($query_args['action'] . '_nonce');
1763
+			$query_args['status'] = $view['slug'];
1764
+			//merge any other arguments sent in.
1765
+			if (isset($extra_query_args[$view['slug']])) {
1766
+				$query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
1767
+			}
1768
+			$this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1769
+		}
1770
+		return $this->_views;
1771
+	}
1772
+
1773
+
1774
+
1775
+	/**
1776
+	 * _entries_per_page_dropdown
1777
+	 * generates a drop down box for selecting the number of visiable rows in an admin page list table
1778
+	 *
1779
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how WP does it.
1780
+	 * @access protected
1781
+	 * @param int $max_entries total number of rows in the table
1782
+	 * @return string
1783
+	 */
1784
+	protected function _entries_per_page_dropdown($max_entries = false)
1785
+	{
1786
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1787
+		$values = array(10, 25, 50, 100);
1788
+		$per_page = ( ! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
1789
+		if ($max_entries) {
1790
+			$values[] = $max_entries;
1791
+			sort($values);
1792
+		}
1793
+		$entries_per_page_dropdown = '
1794 1794
 			<div id="entries-per-page-dv" class="alignleft actions">
1795 1795
 				<label class="hide-if-no-js">
1796 1796
 					Show
1797 1797
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
1798
-        foreach ($values as $value) {
1799
-            if ($value < $max_entries) {
1800
-                $selected = $value == $per_page ? ' selected="' . $per_page . '"' : '';
1801
-                $entries_per_page_dropdown .= '
1798
+		foreach ($values as $value) {
1799
+			if ($value < $max_entries) {
1800
+				$selected = $value == $per_page ? ' selected="' . $per_page . '"' : '';
1801
+				$entries_per_page_dropdown .= '
1802 1802
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
1803
-            }
1804
-        }
1805
-        $selected = $max_entries == $per_page ? ' selected="' . $per_page . '"' : '';
1806
-        $entries_per_page_dropdown .= '
1803
+			}
1804
+		}
1805
+		$selected = $max_entries == $per_page ? ' selected="' . $per_page . '"' : '';
1806
+		$entries_per_page_dropdown .= '
1807 1807
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
1808
-        $entries_per_page_dropdown .= '
1808
+		$entries_per_page_dropdown .= '
1809 1809
 					</select>
1810 1810
 					entries
1811 1811
 				</label>
1812 1812
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
1813 1813
 			</div>
1814 1814
 		';
1815
-        return $entries_per_page_dropdown;
1816
-    }
1817
-
1818
-
1819
-
1820
-    /**
1821
-     *        _set_search_attributes
1822
-     *
1823
-     * @access        protected
1824
-     * @return        void
1825
-     */
1826
-    public function _set_search_attributes()
1827
-    {
1828
-        $this->_template_args['search']['btn_label'] = sprintf(__('Search %s', 'event_espresso'), empty($this->_search_btn_label) ? $this->page_label : $this->_search_btn_label);
1829
-        $this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
1830
-    }
1831
-
1832
-    /*** END LIST TABLE METHODS **/
1833
-    /*****************************/
1834
-    /**
1835
-     *        _add_registered_metaboxes
1836
-     *        this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
1837
-     *
1838
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
1839
-     * @access private
1840
-     * @return void
1841
-     */
1842
-    private function _add_registered_meta_boxes()
1843
-    {
1844
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1845
-        //we only add meta boxes if the page_route calls for it
1846
-        if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
1847
-            && is_array(
1848
-                    $this->_route_config['metaboxes']
1849
-            )
1850
-        ) {
1851
-            // this simply loops through the callbacks provided
1852
-            // and checks if there is a corresponding callback registered by the child
1853
-            // if there is then we go ahead and process the metabox loader.
1854
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
1855
-                // first check for Closures
1856
-                if ($metabox_callback instanceof Closure) {
1857
-                    $result = $metabox_callback();
1858
-                } else if (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
1859
-                    $result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
1860
-                } else {
1861
-                    $result = call_user_func(array($this, &$metabox_callback));
1862
-                }
1863
-                if ($result === false) {
1864
-                    // user error msg
1865
-                    $error_msg = __('An error occurred. The  requested metabox could not be found.', 'event_espresso');
1866
-                    // developer error msg
1867
-                    $error_msg .= '||' . sprintf(
1868
-                                    __(
1869
-                                            'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
1870
-                                            'event_espresso'
1871
-                                    ),
1872
-                                    $metabox_callback
1873
-                            );
1874
-                    throw new EE_Error($error_msg);
1875
-                }
1876
-            }
1877
-        }
1878
-    }
1879
-
1880
-
1881
-
1882
-    /**
1883
-     * _add_screen_columns
1884
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as the dynamic column template and we'll setup the column options for the page.
1885
-     *
1886
-     * @access private
1887
-     * @return void
1888
-     */
1889
-    private function _add_screen_columns()
1890
-    {
1891
-        if (
1892
-                is_array($this->_route_config)
1893
-                && isset($this->_route_config['columns'])
1894
-                && is_array($this->_route_config['columns'])
1895
-                && count($this->_route_config['columns']) === 2
1896
-        ) {
1897
-            add_screen_option('layout_columns', array('max' => (int)$this->_route_config['columns'][0], 'default' => (int)$this->_route_config['columns'][1]));
1898
-            $this->_template_args['num_columns'] = $this->_route_config['columns'][0];
1899
-            $screen_id = $this->_current_screen->id;
1900
-            $screen_columns = (int)get_user_option("screen_layout_$screen_id");
1901
-            $total_columns = ! empty($screen_columns) ? $screen_columns : $this->_route_config['columns'][1];
1902
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
1903
-            $this->_template_args['current_page'] = $this->_wp_page_slug;
1904
-            $this->_template_args['screen'] = $this->_current_screen;
1905
-            $this->_column_template_path = EE_ADMIN_TEMPLATE . 'admin_details_metabox_column_wrapper.template.php';
1906
-            //finally if we don't have has_metaboxes set in the route config let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
1907
-            $this->_route_config['has_metaboxes'] = true;
1908
-        }
1909
-    }
1910
-
1911
-
1912
-
1913
-    /**********************************/
1914
-    /** GLOBALLY AVAILABLE METABOXES **/
1915
-    /**
1916
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply referencing the callback in the _page_config array property.  This way you can be very specific about what pages these get
1917
-     * loaded on.
1918
-     */
1919
-    private function _espresso_news_post_box()
1920
-    {
1921
-        $news_box_title = apply_filters('FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title', __('New @ Event Espresso', 'event_espresso'));
1922
-        add_meta_box('espresso_news_post_box', $news_box_title, array(
1923
-                $this,
1924
-                'espresso_news_post_box',
1925
-        ), $this->_wp_page_slug, 'side');
1926
-    }
1927
-
1928
-
1929
-
1930
-    /**
1931
-     * Code for setting up espresso ratings request metabox.
1932
-     */
1933
-    protected function _espresso_ratings_request()
1934
-    {
1935
-        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
1936
-            return '';
1937
-        }
1938
-        $ratings_box_title = apply_filters('FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title', __('Keep Event Espresso Decaf Free', 'event_espresso'));
1939
-        add_meta_box('espresso_ratings_request', $ratings_box_title, array(
1940
-                $this,
1941
-                'espresso_ratings_request',
1942
-        ), $this->_wp_page_slug, 'side');
1943
-    }
1944
-
1945
-
1946
-
1947
-    /**
1948
-     * Code for setting up espresso ratings request metabox content.
1949
-     */
1950
-    public function espresso_ratings_request()
1951
-    {
1952
-        $template_path = EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php';
1953
-        EEH_Template::display_template($template_path, array());
1954
-    }
1955
-
1956
-
1957
-
1958
-    public static function cached_rss_display($rss_id, $url)
1959
-    {
1960
-        $loading = '<p class="widget-loading hide-if-no-js">' . __('Loading&#8230;') . '</p><p class="hide-if-js">' . __('This widget requires JavaScript.') . '</p>';
1961
-        $doing_ajax = (defined('DOING_AJAX') && DOING_AJAX);
1962
-        $pre = '<div class="espresso-rss-display">' . "\n\t";
1963
-        $pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
1964
-        $post = '</div>' . "\n";
1965
-        $cache_key = 'ee_rss_' . md5($rss_id);
1966
-        if (false != ($output = get_transient($cache_key))) {
1967
-            echo $pre . $output . $post;
1968
-            return true;
1969
-        }
1970
-        if ( ! $doing_ajax) {
1971
-            echo $pre . $loading . $post;
1972
-            return false;
1973
-        }
1974
-        ob_start();
1975
-        wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
1976
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
1977
-        return true;
1978
-    }
1979
-
1980
-
1981
-
1982
-    public function espresso_news_post_box()
1983
-    {
1984
-        ?>
1815
+		return $entries_per_page_dropdown;
1816
+	}
1817
+
1818
+
1819
+
1820
+	/**
1821
+	 *        _set_search_attributes
1822
+	 *
1823
+	 * @access        protected
1824
+	 * @return        void
1825
+	 */
1826
+	public function _set_search_attributes()
1827
+	{
1828
+		$this->_template_args['search']['btn_label'] = sprintf(__('Search %s', 'event_espresso'), empty($this->_search_btn_label) ? $this->page_label : $this->_search_btn_label);
1829
+		$this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
1830
+	}
1831
+
1832
+	/*** END LIST TABLE METHODS **/
1833
+	/*****************************/
1834
+	/**
1835
+	 *        _add_registered_metaboxes
1836
+	 *        this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
1837
+	 *
1838
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
1839
+	 * @access private
1840
+	 * @return void
1841
+	 */
1842
+	private function _add_registered_meta_boxes()
1843
+	{
1844
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1845
+		//we only add meta boxes if the page_route calls for it
1846
+		if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
1847
+			&& is_array(
1848
+					$this->_route_config['metaboxes']
1849
+			)
1850
+		) {
1851
+			// this simply loops through the callbacks provided
1852
+			// and checks if there is a corresponding callback registered by the child
1853
+			// if there is then we go ahead and process the metabox loader.
1854
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
1855
+				// first check for Closures
1856
+				if ($metabox_callback instanceof Closure) {
1857
+					$result = $metabox_callback();
1858
+				} else if (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
1859
+					$result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
1860
+				} else {
1861
+					$result = call_user_func(array($this, &$metabox_callback));
1862
+				}
1863
+				if ($result === false) {
1864
+					// user error msg
1865
+					$error_msg = __('An error occurred. The  requested metabox could not be found.', 'event_espresso');
1866
+					// developer error msg
1867
+					$error_msg .= '||' . sprintf(
1868
+									__(
1869
+											'The metabox with the string "%s" could not be called. Check that the spelling for method names and actions in the "_page_config[\'metaboxes\']" array are all correct.',
1870
+											'event_espresso'
1871
+									),
1872
+									$metabox_callback
1873
+							);
1874
+					throw new EE_Error($error_msg);
1875
+				}
1876
+			}
1877
+		}
1878
+	}
1879
+
1880
+
1881
+
1882
+	/**
1883
+	 * _add_screen_columns
1884
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as the dynamic column template and we'll setup the column options for the page.
1885
+	 *
1886
+	 * @access private
1887
+	 * @return void
1888
+	 */
1889
+	private function _add_screen_columns()
1890
+	{
1891
+		if (
1892
+				is_array($this->_route_config)
1893
+				&& isset($this->_route_config['columns'])
1894
+				&& is_array($this->_route_config['columns'])
1895
+				&& count($this->_route_config['columns']) === 2
1896
+		) {
1897
+			add_screen_option('layout_columns', array('max' => (int)$this->_route_config['columns'][0], 'default' => (int)$this->_route_config['columns'][1]));
1898
+			$this->_template_args['num_columns'] = $this->_route_config['columns'][0];
1899
+			$screen_id = $this->_current_screen->id;
1900
+			$screen_columns = (int)get_user_option("screen_layout_$screen_id");
1901
+			$total_columns = ! empty($screen_columns) ? $screen_columns : $this->_route_config['columns'][1];
1902
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
1903
+			$this->_template_args['current_page'] = $this->_wp_page_slug;
1904
+			$this->_template_args['screen'] = $this->_current_screen;
1905
+			$this->_column_template_path = EE_ADMIN_TEMPLATE . 'admin_details_metabox_column_wrapper.template.php';
1906
+			//finally if we don't have has_metaboxes set in the route config let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
1907
+			$this->_route_config['has_metaboxes'] = true;
1908
+		}
1909
+	}
1910
+
1911
+
1912
+
1913
+	/**********************************/
1914
+	/** GLOBALLY AVAILABLE METABOXES **/
1915
+	/**
1916
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply referencing the callback in the _page_config array property.  This way you can be very specific about what pages these get
1917
+	 * loaded on.
1918
+	 */
1919
+	private function _espresso_news_post_box()
1920
+	{
1921
+		$news_box_title = apply_filters('FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title', __('New @ Event Espresso', 'event_espresso'));
1922
+		add_meta_box('espresso_news_post_box', $news_box_title, array(
1923
+				$this,
1924
+				'espresso_news_post_box',
1925
+		), $this->_wp_page_slug, 'side');
1926
+	}
1927
+
1928
+
1929
+
1930
+	/**
1931
+	 * Code for setting up espresso ratings request metabox.
1932
+	 */
1933
+	protected function _espresso_ratings_request()
1934
+	{
1935
+		if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
1936
+			return '';
1937
+		}
1938
+		$ratings_box_title = apply_filters('FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title', __('Keep Event Espresso Decaf Free', 'event_espresso'));
1939
+		add_meta_box('espresso_ratings_request', $ratings_box_title, array(
1940
+				$this,
1941
+				'espresso_ratings_request',
1942
+		), $this->_wp_page_slug, 'side');
1943
+	}
1944
+
1945
+
1946
+
1947
+	/**
1948
+	 * Code for setting up espresso ratings request metabox content.
1949
+	 */
1950
+	public function espresso_ratings_request()
1951
+	{
1952
+		$template_path = EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php';
1953
+		EEH_Template::display_template($template_path, array());
1954
+	}
1955
+
1956
+
1957
+
1958
+	public static function cached_rss_display($rss_id, $url)
1959
+	{
1960
+		$loading = '<p class="widget-loading hide-if-no-js">' . __('Loading&#8230;') . '</p><p class="hide-if-js">' . __('This widget requires JavaScript.') . '</p>';
1961
+		$doing_ajax = (defined('DOING_AJAX') && DOING_AJAX);
1962
+		$pre = '<div class="espresso-rss-display">' . "\n\t";
1963
+		$pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
1964
+		$post = '</div>' . "\n";
1965
+		$cache_key = 'ee_rss_' . md5($rss_id);
1966
+		if (false != ($output = get_transient($cache_key))) {
1967
+			echo $pre . $output . $post;
1968
+			return true;
1969
+		}
1970
+		if ( ! $doing_ajax) {
1971
+			echo $pre . $loading . $post;
1972
+			return false;
1973
+		}
1974
+		ob_start();
1975
+		wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
1976
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
1977
+		return true;
1978
+	}
1979
+
1980
+
1981
+
1982
+	public function espresso_news_post_box()
1983
+	{
1984
+		?>
1985 1985
         <div class="padding">
1986 1986
             <div id="espresso_news_post_box_content" class="infolinks">
1987 1987
                 <?php
1988
-                // Get RSS Feed(s)
1989
-                $feed_url = apply_filters('FHEE__EE_Admin_Page__espresso_news_post_box__feed_url', 'http://eventespresso.com/feed/');
1990
-                $url = urlencode($feed_url);
1991
-                self::cached_rss_display('espresso_news_post_box_content', $url);
1992
-                ?>
1988
+				// Get RSS Feed(s)
1989
+				$feed_url = apply_filters('FHEE__EE_Admin_Page__espresso_news_post_box__feed_url', 'http://eventespresso.com/feed/');
1990
+				$url = urlencode($feed_url);
1991
+				self::cached_rss_display('espresso_news_post_box_content', $url);
1992
+				?>
1993 1993
             </div>
1994 1994
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
1995 1995
         </div>
1996 1996
         <?php
1997
-    }
1998
-
1999
-
2000
-
2001
-    private function _espresso_links_post_box()
2002
-    {
2003
-        //Hiding until we actually have content to put in here...
2004
-        //add_meta_box('espresso_links_post_box', __('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2005
-    }
2006
-
2007
-
2008
-
2009
-    public function espresso_links_post_box()
2010
-    {
2011
-        //Hiding until we actually have content to put in here...
2012
-        //$templatepath = EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php';
2013
-        //EEH_Template::display_template( $templatepath );
2014
-    }
2015
-
2016
-
2017
-
2018
-    protected function _espresso_sponsors_post_box()
2019
-    {
2020
-        $show_sponsors = apply_filters('FHEE_show_sponsors_meta_box', true);
2021
-        if ($show_sponsors) {
2022
-            add_meta_box('espresso_sponsors_post_box', __('Event Espresso Highlights', 'event_espresso'), array($this, 'espresso_sponsors_post_box'), $this->_wp_page_slug, 'side');
2023
-        }
2024
-    }
2025
-
2026
-
2027
-
2028
-    public function espresso_sponsors_post_box()
2029
-    {
2030
-        $templatepath = EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php';
2031
-        EEH_Template::display_template($templatepath);
2032
-    }
2033
-
2034
-
2035
-
2036
-    private function _publish_post_box()
2037
-    {
2038
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2039
-        //if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array then we'll use that for the metabox label.  Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2040
-        if ( ! empty($this->_labels['publishbox'])) {
2041
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action] : $this->_labels['publishbox'];
2042
-        } else {
2043
-            $box_label = __('Publish', 'event_espresso');
2044
-        }
2045
-        $box_label = apply_filters('FHEE__EE_Admin_Page___publish_post_box__box_label', $box_label, $this->_req_action, $this);
2046
-        add_meta_box($meta_box_ref, $box_label, array($this, 'editor_overview'), $this->_current_screen->id, 'side', 'high');
2047
-    }
2048
-
2049
-
2050
-
2051
-    public function editor_overview()
2052
-    {
2053
-        //if we have extra content set let's add it in if not make sure its empty
2054
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content']) ? $this->_template_args['publish_box_extra_content'] : '';
2055
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php';
2056
-        echo EEH_Template::display_template($template_path, $this->_template_args, true);
2057
-    }
2058
-
2059
-
2060
-    /** end of globally available metaboxes section **/
2061
-    /*************************************************/
2062
-    /**
2063
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2064
-     * protected method.
2065
-     *
2066
-     * @see   $this->_set_publish_post_box_vars for param details
2067
-     * @since 4.6.0
2068
-     */
2069
-    public function set_publish_post_box_vars($name = null, $id = false, $delete = false, $save_close_redirect_URL = null, $both_btns = true)
2070
-    {
2071
-        $this->_set_publish_post_box_vars($name, $id, $delete, $save_close_redirect_URL, $both_btns);
2072
-    }
2073
-
2074
-
2075
-
2076
-    /**
2077
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2078
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2079
-     * save, and save and close buttons to work properly, then you will want to include a
2080
-     * values for the name and id arguments.
2081
-     *
2082
-     * @todo  Add in validation for name/id arguments.
2083
-     * @param    string  $name                    key used for the action ID (i.e. event_id)
2084
-     * @param    int     $id                      id attached to the item published
2085
-     * @param    string  $delete                  page route callback for the delete action
2086
-     * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2087
-     * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just the Save button
2088
-     * @throws \EE_Error
2089
-     */
2090
-    protected function _set_publish_post_box_vars(
2091
-            $name = '',
2092
-            $id = 0,
2093
-            $delete = '',
2094
-            $save_close_redirect_URL = '',
2095
-            $both_btns = true
2096
-    ) {
2097
-        // if Save & Close, use a custom redirect URL or default to the main page?
2098
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL) ? $save_close_redirect_URL : $this->_admin_base_url;
2099
-        // create the Save & Close and Save buttons
2100
-        $this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2101
-        //if we have extra content set let's add it in if not make sure its empty
2102
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content']) ? $this->_template_args['publish_box_extra_content'] : '';
2103
-        if ($delete && ! empty($id)) {
2104
-            //make sure we have a default if just true is sent.
2105
-            $delete = ! empty($delete) ? $delete : 'delete';
2106
-            $delete_link_args = array($name => $id);
2107
-            $delete = $this->get_action_link_or_button(
2108
-                    $delete,
2109
-                    $delete,
2110
-                    $delete_link_args,
2111
-                    'submitdelete deletion',
2112
-                    '',
2113
-                    false
2114
-            );
2115
-        }
2116
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2117
-        if ( ! empty($name) && ! empty($id)) {
2118
-            $hidden_field_arr[$name] = array(
2119
-                    'type'  => 'hidden',
2120
-                    'value' => $id,
2121
-            );
2122
-            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2123
-        } else {
2124
-            $hf = '';
2125
-        }
2126
-        // add hidden field
2127
-        $this->_template_args['publish_hidden_fields'] = ! empty($hf) ? $hf[$name]['field'] : $hf;
2128
-    }
2129
-
2130
-
2131
-
2132
-    /**
2133
-     *        displays an error message to ppl who have javascript disabled
2134
-     *
2135
-     * @access        private
2136
-     * @return        string
2137
-     */
2138
-    private function _display_no_javascript_warning()
2139
-    {
2140
-        ?>
1997
+	}
1998
+
1999
+
2000
+
2001
+	private function _espresso_links_post_box()
2002
+	{
2003
+		//Hiding until we actually have content to put in here...
2004
+		//add_meta_box('espresso_links_post_box', __('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2005
+	}
2006
+
2007
+
2008
+
2009
+	public function espresso_links_post_box()
2010
+	{
2011
+		//Hiding until we actually have content to put in here...
2012
+		//$templatepath = EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php';
2013
+		//EEH_Template::display_template( $templatepath );
2014
+	}
2015
+
2016
+
2017
+
2018
+	protected function _espresso_sponsors_post_box()
2019
+	{
2020
+		$show_sponsors = apply_filters('FHEE_show_sponsors_meta_box', true);
2021
+		if ($show_sponsors) {
2022
+			add_meta_box('espresso_sponsors_post_box', __('Event Espresso Highlights', 'event_espresso'), array($this, 'espresso_sponsors_post_box'), $this->_wp_page_slug, 'side');
2023
+		}
2024
+	}
2025
+
2026
+
2027
+
2028
+	public function espresso_sponsors_post_box()
2029
+	{
2030
+		$templatepath = EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php';
2031
+		EEH_Template::display_template($templatepath);
2032
+	}
2033
+
2034
+
2035
+
2036
+	private function _publish_post_box()
2037
+	{
2038
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2039
+		//if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array then we'll use that for the metabox label.  Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2040
+		if ( ! empty($this->_labels['publishbox'])) {
2041
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][$this->_req_action] : $this->_labels['publishbox'];
2042
+		} else {
2043
+			$box_label = __('Publish', 'event_espresso');
2044
+		}
2045
+		$box_label = apply_filters('FHEE__EE_Admin_Page___publish_post_box__box_label', $box_label, $this->_req_action, $this);
2046
+		add_meta_box($meta_box_ref, $box_label, array($this, 'editor_overview'), $this->_current_screen->id, 'side', 'high');
2047
+	}
2048
+
2049
+
2050
+
2051
+	public function editor_overview()
2052
+	{
2053
+		//if we have extra content set let's add it in if not make sure its empty
2054
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content']) ? $this->_template_args['publish_box_extra_content'] : '';
2055
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php';
2056
+		echo EEH_Template::display_template($template_path, $this->_template_args, true);
2057
+	}
2058
+
2059
+
2060
+	/** end of globally available metaboxes section **/
2061
+	/*************************************************/
2062
+	/**
2063
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2064
+	 * protected method.
2065
+	 *
2066
+	 * @see   $this->_set_publish_post_box_vars for param details
2067
+	 * @since 4.6.0
2068
+	 */
2069
+	public function set_publish_post_box_vars($name = null, $id = false, $delete = false, $save_close_redirect_URL = null, $both_btns = true)
2070
+	{
2071
+		$this->_set_publish_post_box_vars($name, $id, $delete, $save_close_redirect_URL, $both_btns);
2072
+	}
2073
+
2074
+
2075
+
2076
+	/**
2077
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2078
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2079
+	 * save, and save and close buttons to work properly, then you will want to include a
2080
+	 * values for the name and id arguments.
2081
+	 *
2082
+	 * @todo  Add in validation for name/id arguments.
2083
+	 * @param    string  $name                    key used for the action ID (i.e. event_id)
2084
+	 * @param    int     $id                      id attached to the item published
2085
+	 * @param    string  $delete                  page route callback for the delete action
2086
+	 * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2087
+	 * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just the Save button
2088
+	 * @throws \EE_Error
2089
+	 */
2090
+	protected function _set_publish_post_box_vars(
2091
+			$name = '',
2092
+			$id = 0,
2093
+			$delete = '',
2094
+			$save_close_redirect_URL = '',
2095
+			$both_btns = true
2096
+	) {
2097
+		// if Save & Close, use a custom redirect URL or default to the main page?
2098
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL) ? $save_close_redirect_URL : $this->_admin_base_url;
2099
+		// create the Save & Close and Save buttons
2100
+		$this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2101
+		//if we have extra content set let's add it in if not make sure its empty
2102
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content']) ? $this->_template_args['publish_box_extra_content'] : '';
2103
+		if ($delete && ! empty($id)) {
2104
+			//make sure we have a default if just true is sent.
2105
+			$delete = ! empty($delete) ? $delete : 'delete';
2106
+			$delete_link_args = array($name => $id);
2107
+			$delete = $this->get_action_link_or_button(
2108
+					$delete,
2109
+					$delete,
2110
+					$delete_link_args,
2111
+					'submitdelete deletion',
2112
+					'',
2113
+					false
2114
+			);
2115
+		}
2116
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2117
+		if ( ! empty($name) && ! empty($id)) {
2118
+			$hidden_field_arr[$name] = array(
2119
+					'type'  => 'hidden',
2120
+					'value' => $id,
2121
+			);
2122
+			$hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2123
+		} else {
2124
+			$hf = '';
2125
+		}
2126
+		// add hidden field
2127
+		$this->_template_args['publish_hidden_fields'] = ! empty($hf) ? $hf[$name]['field'] : $hf;
2128
+	}
2129
+
2130
+
2131
+
2132
+	/**
2133
+	 *        displays an error message to ppl who have javascript disabled
2134
+	 *
2135
+	 * @access        private
2136
+	 * @return        string
2137
+	 */
2138
+	private function _display_no_javascript_warning()
2139
+	{
2140
+		?>
2141 2141
         <noscript>
2142 2142
             <div id="no-js-message" class="error">
2143 2143
                 <p style="font-size:1.3em;">
@@ -2147,1267 +2147,1267 @@  discard block
 block discarded – undo
2147 2147
             </div>
2148 2148
         </noscript>
2149 2149
         <?php
2150
-    }
2150
+	}
2151 2151
 
2152 2152
 
2153 2153
 
2154
-    /**
2155
-     *        displays espresso success and/or error notices
2156
-     *
2157
-     * @access        private
2158
-     * @return        string
2159
-     */
2160
-    private function _display_espresso_notices()
2161
-    {
2162
-        $notices = $this->_get_transient(true);
2163
-        echo stripslashes($notices);
2164
-    }
2154
+	/**
2155
+	 *        displays espresso success and/or error notices
2156
+	 *
2157
+	 * @access        private
2158
+	 * @return        string
2159
+	 */
2160
+	private function _display_espresso_notices()
2161
+	{
2162
+		$notices = $this->_get_transient(true);
2163
+		echo stripslashes($notices);
2164
+	}
2165 2165
 
2166 2166
 
2167 2167
 
2168
-    /**
2169
-     *        spinny things pacify the masses
2170
-     *
2171
-     * @access private
2172
-     * @return string
2173
-     */
2174
-    protected function _add_admin_page_ajax_loading_img()
2175
-    {
2176
-        ?>
2168
+	/**
2169
+	 *        spinny things pacify the masses
2170
+	 *
2171
+	 * @access private
2172
+	 * @return string
2173
+	 */
2174
+	protected function _add_admin_page_ajax_loading_img()
2175
+	{
2176
+		?>
2177 2177
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2178 2178
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php esc_html_e('loading...', 'event_espresso'); ?></span>
2179 2179
         </div>
2180 2180
         <?php
2181
-    }
2181
+	}
2182 2182
 
2183 2183
 
2184 2184
 
2185
-    /**
2186
-     *        add admin page overlay for modal boxes
2187
-     *
2188
-     * @access private
2189
-     * @return string
2190
-     */
2191
-    protected function _add_admin_page_overlay()
2192
-    {
2193
-        ?>
2185
+	/**
2186
+	 *        add admin page overlay for modal boxes
2187
+	 *
2188
+	 * @access private
2189
+	 * @return string
2190
+	 */
2191
+	protected function _add_admin_page_overlay()
2192
+	{
2193
+		?>
2194 2194
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2195 2195
         <?php
2196
-    }
2197
-
2198
-
2199
-
2200
-    /**
2201
-     * facade for add_meta_box
2202
-     *
2203
-     * @param string  $action        where the metabox get's displayed
2204
-     * @param string  $title         Title of Metabox (output in metabox header)
2205
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback instead of the one created in here.
2206
-     * @param array   $callback_args an array of args supplied for the metabox
2207
-     * @param string  $column        what metabox column
2208
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2209
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function created but just set our own callback for wp's add_meta_box.
2210
-     */
2211
-    public function _add_admin_page_meta_box($action, $title, $callback, $callback_args, $column = 'normal', $priority = 'high', $create_func = true)
2212
-    {
2213
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2214
-        //if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2215
-        if (empty($callback_args) && $create_func) {
2216
-            $callback_args = array(
2217
-                    'template_path' => $this->_template_path,
2218
-                    'template_args' => $this->_template_args,
2219
-            );
2220
-        }
2221
-        //if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2222
-        $call_back_func = $create_func ? create_function('$post, $metabox',
2223
-                'do_action( "AHEE_log", __FILE__, __FUNCTION__, ""); echo EEH_Template::display_template( $metabox["args"]["template_path"], $metabox["args"]["template_args"], TRUE );') : $callback;
2224
-        add_meta_box(str_replace('_', '-', $action) . '-mbox', $title, $call_back_func, $this->_wp_page_slug, $column, $priority, $callback_args);
2225
-    }
2226
-
2227
-
2228
-
2229
-    /**
2230
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2231
-     *
2232
-     * @return [type] [description]
2233
-     */
2234
-    public function display_admin_page_with_metabox_columns()
2235
-    {
2236
-        $this->_template_args['post_body_content'] = $this->_template_args['admin_page_content'];
2237
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_column_template_path, $this->_template_args, true);
2238
-        //the final wrapper
2239
-        $this->admin_page_wrapper();
2240
-    }
2241
-
2242
-
2243
-
2244
-    /**
2245
-     *        generates  HTML wrapper for an admin details page
2246
-     *
2247
-     * @access public
2248
-     * @return void
2249
-     */
2250
-    public function display_admin_page_with_sidebar()
2251
-    {
2252
-        $this->_display_admin_page(true);
2253
-    }
2254
-
2255
-
2256
-
2257
-    /**
2258
-     *        generates  HTML wrapper for an admin details page (except no sidebar)
2259
-     *
2260
-     * @access public
2261
-     * @return void
2262
-     */
2263
-    public function display_admin_page_with_no_sidebar()
2264
-    {
2265
-        $this->_display_admin_page();
2266
-    }
2267
-
2268
-
2269
-
2270
-    /**
2271
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2272
-     *
2273
-     * @access public
2274
-     * @return void
2275
-     */
2276
-    public function display_about_admin_page()
2277
-    {
2278
-        $this->_display_admin_page(false, true);
2279
-    }
2280
-
2281
-
2282
-
2283
-    /**
2284
-     * display_admin_page
2285
-     * contains the code for actually displaying an admin page
2286
-     *
2287
-     * @access private
2288
-     * @param  boolean $sidebar true with sidebar, false without
2289
-     * @param  boolean $about   use the about admin wrapper instead of the default.
2290
-     * @return void
2291
-     */
2292
-    private function _display_admin_page($sidebar = false, $about = false)
2293
-    {
2294
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2295
-        //custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2296
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2297
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2298
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2299
-        $this->_template_args['current_page'] = $this->_wp_page_slug;
2300
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2301
-                ? 'poststuff'
2302
-                : 'espresso-default-admin';
2303
-        $template_path = $sidebar
2304
-                ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2305
-                : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2306
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2307
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2308
-        }
2309
-        $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2310
-        $this->_template_args['post_body_content'] = isset($this->_template_args['admin_page_content']) ? $this->_template_args['admin_page_content'] : '';
2311
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content']) ? $this->_template_args['before_admin_page_content'] : '';
2312
-        $this->_template_args['after_admin_page_content'] = isset($this->_template_args['after_admin_page_content']) ? $this->_template_args['after_admin_page_content'] : '';
2313
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path, $this->_template_args, true);
2314
-        // the final template wrapper
2315
-        $this->admin_page_wrapper($about);
2316
-    }
2317
-
2318
-
2319
-
2320
-    /**
2321
-     * This is used to display caf preview pages.
2322
-     *
2323
-     * @since 4.3.2
2324
-     * @param string $utm_campaign_source what is the key used for google analytics link
2325
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2326
-     * @return void
2327
-     * @throws \EE_Error
2328
-     */
2329
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2330
-    {
2331
-        //let's generate a default preview action button if there isn't one already present.
2332
-        $this->_labels['buttons']['buy_now'] = __('Upgrade to Event Espresso 4 Right Now', 'event_espresso');
2333
-        $buy_now_url = add_query_arg(
2334
-                array(
2335
-                        'ee_ver'       => 'ee4',
2336
-                        'utm_source'   => 'ee4_plugin_admin',
2337
-                        'utm_medium'   => 'link',
2338
-                        'utm_campaign' => $utm_campaign_source,
2339
-                        'utm_content'  => 'buy_now_button',
2340
-                ),
2341
-                'http://eventespresso.com/pricing/'
2342
-        );
2343
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2344
-                ? $this->get_action_link_or_button(
2345
-                        '',
2346
-                        'buy_now',
2347
-                        array(),
2348
-                        'button-primary button-large',
2349
-                        $buy_now_url,
2350
-                        true
2351
-                )
2352
-                : $this->_template_args['preview_action_button'];
2353
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php';
2354
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2355
-                $template_path,
2356
-                $this->_template_args,
2357
-                true
2358
-        );
2359
-        $this->_display_admin_page($display_sidebar);
2360
-    }
2361
-
2362
-
2363
-
2364
-    /**
2365
-     * display_admin_list_table_page_with_sidebar
2366
-     * generates HTML wrapper for an admin_page with list_table
2367
-     *
2368
-     * @access public
2369
-     * @return void
2370
-     */
2371
-    public function display_admin_list_table_page_with_sidebar()
2372
-    {
2373
-        $this->_display_admin_list_table_page(true);
2374
-    }
2375
-
2376
-
2377
-
2378
-    /**
2379
-     * display_admin_list_table_page_with_no_sidebar
2380
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2381
-     *
2382
-     * @access public
2383
-     * @return void
2384
-     */
2385
-    public function display_admin_list_table_page_with_no_sidebar()
2386
-    {
2387
-        $this->_display_admin_list_table_page();
2388
-    }
2389
-
2390
-
2391
-
2392
-    /**
2393
-     * generates html wrapper for an admin_list_table page
2394
-     *
2395
-     * @access private
2396
-     * @param boolean $sidebar whether to display with sidebar or not.
2397
-     * @return void
2398
-     */
2399
-    private function _display_admin_list_table_page($sidebar = false)
2400
-    {
2401
-        //setup search attributes
2402
-        $this->_set_search_attributes();
2403
-        $this->_template_args['current_page'] = $this->_wp_page_slug;
2404
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2405
-        $this->_template_args['table_url'] = defined('DOING_AJAX')
2406
-                ? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2407
-                : add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
2408
-        $this->_template_args['list_table'] = $this->_list_table_object;
2409
-        $this->_template_args['current_route'] = $this->_req_action;
2410
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2411
-        $ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2412
-        if ( ! empty($ajax_sorting_callback)) {
2413
-            $sortable_list_table_form_fields = wp_nonce_field(
2414
-                    $ajax_sorting_callback . '_nonce',
2415
-                    $ajax_sorting_callback . '_nonce',
2416
-                    false,
2417
-                    false
2418
-            );
2419
-            //			$reorder_action = 'espresso_' . $ajax_sorting_callback . '_nonce';
2420
-            //			$sortable_list_table_form_fields = wp_nonce_field( $reorder_action, 'ajax_table_sort_nonce', FALSE, FALSE );
2421
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="' . $this->page_slug . '" />';
2422
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="' . $ajax_sorting_callback . '" />';
2423
-        } else {
2424
-            $sortable_list_table_form_fields = '';
2425
-        }
2426
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2427
-        $hidden_form_fields = isset($this->_template_args['list_table_hidden_fields']) ? $this->_template_args['list_table_hidden_fields'] : '';
2428
-        $nonce_ref = $this->_req_action . '_nonce';
2429
-        $hidden_form_fields .= '<input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2430
-        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2431
-        //display message about search results?
2432
-        $this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
2433
-                ? '<p class="ee-search-results">' . sprintf(
2434
-                        esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2435
-                        trim($this->_req_data['s'], '%')
2436
-                ) . '</p>'
2437
-                : '';
2438
-        // filter before_list_table template arg
2439
-        $this->_template_args['before_list_table'] = apply_filters(
2440
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2441
-            $this->_template_args['before_list_table'],
2442
-            $this->page_slug,
2443
-            $this->_req_data,
2444
-            $this->_req_action
2445
-        );
2446
-        // convert to array and filter again
2447
-        // arrays are easier to inject new items in a specific location,
2448
-        // but would not be backwards compatible, so we have to add a new filter
2449
-        $this->_template_args['before_list_table'] = implode(
2450
-            " \n",
2451
-            (array) apply_filters(
2452
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2453
-                (array) $this->_template_args['before_list_table'],
2454
-                $this->page_slug,
2455
-                $this->_req_data,
2456
-                $this->_req_action
2457
-            )
2458
-        );
2459
-        // filter after_list_table template arg
2460
-        $this->_template_args['after_list_table'] = apply_filters(
2461
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2462
-            $this->_template_args['after_list_table'],
2463
-            $this->page_slug,
2464
-            $this->_req_data,
2465
-            $this->_req_action
2466
-        );
2467
-        // convert to array and filter again
2468
-        // arrays are easier to inject new items in a specific location,
2469
-        // but would not be backwards compatible, so we have to add a new filter
2470
-        $this->_template_args['after_list_table'] = implode(
2471
-            " \n",
2472
-            (array) apply_filters(
2473
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
2474
-                (array) $this->_template_args['after_list_table'],
2475
-                $this->page_slug,
2476
-                $this->_req_data,
2477
-                $this->_req_action
2478
-            )
2479
-        );
2480
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2481
-                $template_path,
2482
-                $this->_template_args,
2483
-                true
2484
-        );
2485
-        // the final template wrapper
2486
-        if ($sidebar) {
2487
-            $this->display_admin_page_with_sidebar();
2488
-        } else {
2489
-            $this->display_admin_page_with_no_sidebar();
2490
-        }
2491
-    }
2492
-
2493
-
2494
-
2495
-    /**
2496
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the html string for the legend.
2497
-     * $items are expected in an array in the following format:
2498
-     * $legend_items = array(
2499
-     *        'item_id' => array(
2500
-     *            'icon' => 'http://url_to_icon_being_described.png',
2501
-     *            'desc' => __('localized description of item');
2502
-     *        )
2503
-     * );
2504
-     *
2505
-     * @param  array $items see above for format of array
2506
-     * @return string        html string of legend
2507
-     */
2508
-    protected function _display_legend($items)
2509
-    {
2510
-        $this->_template_args['items'] = apply_filters('FHEE__EE_Admin_Page___display_legend__items', (array)$items, $this);
2511
-        $legend_template = EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php';
2512
-        return EEH_Template::display_template($legend_template, $this->_template_args, true);
2513
-    }
2514
-
2515
-
2516
-    /**
2517
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
2518
-     * The returned json object is created from an array in the following format:
2519
-     * array(
2520
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
2521
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
2522
-     *  'notices' => '', // - contains any EE_Error formatted notices
2523
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
2524
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js. We're also going to include the template args with every package (so js can pick out any
2525
-     *  specific template args that might be included in here)
2526
-     * )
2527
-     * The json object is populated by whatever is set in the $_template_args property.
2528
-     *
2529
-     * @param bool  $sticky_notices Used to indicate whether you want to ensure notices are added to a transient instead of displayed.
2530
-     * @param array $notices_arguments  Use this to pass any additional args on to the _process_notices.
2531
-     * @return void
2532
-     */
2533
-    protected function _return_json($sticky_notices = false, $notices_arguments = array())
2534
-    {
2535
-        //make sure any EE_Error notices have been handled.
2536
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
2537
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
2538
-        unset($this->_template_args['data']);
2539
-        $json = array(
2540
-                'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
2541
-                'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
2542
-                'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
2543
-                'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
2544
-                'notices'   => EE_Error::get_notices(),
2545
-                'content'   => isset($this->_template_args['admin_page_content']) ? $this->_template_args['admin_page_content'] : '',
2546
-                'data'      => array_merge($data, array('template_args' => $this->_template_args)),
2547
-                'isEEajax'  => true //special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
2548
-        );
2549
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
2550
-        if (null === error_get_last() || ! headers_sent()) {
2551
-            header('Content-Type: application/json; charset=UTF-8');
2552
-        }
2553
-        echo wp_json_encode($json);
2554
-
2555
-        exit();
2556
-    }
2557
-
2558
-
2559
-
2560
-    /**
2561
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
2562
-     *
2563
-     * @return void
2564
-     * @throws EE_Error
2565
-     */
2566
-    public function return_json()
2567
-    {
2568
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2569
-            $this->_return_json();
2570
-        } else {
2571
-            throw new EE_Error(sprintf(__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'), __FUNCTION__));
2572
-        }
2573
-    }
2574
-
2575
-
2576
-
2577
-    /**
2578
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
2579
-     *
2580
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
2581
-     * @access   public
2582
-     */
2583
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
2584
-    {
2585
-        $this->_hook_obj = $hook_obj;
2586
-    }
2587
-
2588
-
2589
-
2590
-    /**
2591
-     *        generates  HTML wrapper with Tabbed nav for an admin page
2592
-     *
2593
-     * @access public
2594
-     * @param  boolean $about whether to use the special about page wrapper or default.
2595
-     * @return void
2596
-     */
2597
-    public function admin_page_wrapper($about = false)
2598
-    {
2599
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2600
-        $this->_nav_tabs = $this->_get_main_nav_tabs();
2601
-        $this->_template_args['nav_tabs'] = $this->_nav_tabs;
2602
-        $this->_template_args['admin_page_title'] = $this->_admin_page_title;
2603
-        $this->_template_args['before_admin_page_content'] = apply_filters('FHEE_before_admin_page_content' . $this->_current_page . $this->_current_view,
2604
-                isset($this->_template_args['before_admin_page_content']) ? $this->_template_args['before_admin_page_content'] : '');
2605
-        $this->_template_args['after_admin_page_content'] = apply_filters('FHEE_after_admin_page_content' . $this->_current_page . $this->_current_view,
2606
-                isset($this->_template_args['after_admin_page_content']) ? $this->_template_args['after_admin_page_content'] : '');
2607
-        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
2608
-        // load settings page wrapper template
2609
-        $template_path = ! defined('DOING_AJAX') ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php' : EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php';
2610
-        //about page?
2611
-        $template_path = $about ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php' : $template_path;
2612
-        if (defined('DOING_AJAX')) {
2613
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path, $this->_template_args, true);
2614
-            $this->_return_json();
2615
-        } else {
2616
-            EEH_Template::display_template($template_path, $this->_template_args);
2617
-        }
2618
-    }
2619
-
2620
-
2621
-
2622
-    /**
2623
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
2624
-     *
2625
-     * @return string html
2626
-     */
2627
-    protected function _get_main_nav_tabs()
2628
-    {
2629
-        //let's generate the html using the EEH_Tabbed_Content helper.  We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute (rather than setting in the page_routes array)
2630
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
2631
-    }
2632
-
2633
-
2634
-
2635
-    /**
2636
-     *        sort nav tabs
2637
-     *
2638
-     * @access public
2639
-     * @param $a
2640
-     * @param $b
2641
-     * @return int
2642
-     */
2643
-    private function _sort_nav_tabs($a, $b)
2644
-    {
2645
-        if ($a['order'] == $b['order']) {
2646
-            return 0;
2647
-        }
2648
-        return ($a['order'] < $b['order']) ? -1 : 1;
2649
-    }
2650
-
2651
-
2652
-
2653
-    /**
2654
-     *    generates HTML for the forms used on admin pages
2655
-     *
2656
-     * @access protected
2657
-     * @param    array $input_vars - array of input field details
2658
-     * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to use)
2659
-     * @return string
2660
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
2661
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
2662
-     */
2663
-    protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
2664
-    {
2665
-        $content = $generator == 'string' ? EEH_Form_Fields::get_form_fields($input_vars, $id) : EEH_Form_Fields::get_form_fields_array($input_vars);
2666
-        return $content;
2667
-    }
2668
-
2669
-
2670
-
2671
-    /**
2672
-     * generates the "Save" and "Save & Close" buttons for edit forms
2673
-     *
2674
-     * @access protected
2675
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save & Close" button.
2676
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] => 'Save', [1] => 'save & close')
2677
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e. via the "name" value in the button).  We can also use this to just dump default actions by submitting some other value.
2678
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it will use the $referrer string. IF null, then we don't do ANYTHING on save and close (normal form handling).
2679
-     */
2680
-    protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
2681
-    {
2682
-        //make sure $text and $actions are in an array
2683
-        $text = (array)$text;
2684
-        $actions = (array)$actions;
2685
-        $referrer_url = empty($referrer) ? '' : $referrer;
2686
-        $referrer_url = ! $referrer ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="' . $_SERVER['REQUEST_URI'] . '" />'
2687
-                : '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="' . $referrer . '" />';
2688
-        $button_text = ! empty($text) ? $text : array(__('Save', 'event_espresso'), __('Save and Close', 'event_espresso'));
2689
-        $default_names = array('save', 'save_and_close');
2690
-        //add in a hidden index for the current page (so save and close redirects properly)
2691
-        $this->_template_args['save_buttons'] = $referrer_url;
2692
-        foreach ($button_text as $key => $button) {
2693
-            $ref = $default_names[$key];
2694
-            $id = $this->_current_view . '_' . $ref;
2695
-            $name = ! empty($actions) ? $actions[$key] : $ref;
2696
-            $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary ' . $ref . '" value="' . $button . '" name="' . $name . '" id="' . $id . '" />';
2697
-            if ( ! $both) {
2698
-                break;
2699
-            }
2700
-        }
2701
-    }
2702
-
2703
-
2704
-
2705
-    /**
2706
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
2707
-     *
2708
-     * @see   $this->_set_add_edit_form_tags() for details on params
2709
-     * @since 4.6.0
2710
-     * @param string $route
2711
-     * @param array  $additional_hidden_fields
2712
-     */
2713
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
2714
-    {
2715
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
2716
-    }
2717
-
2718
-
2719
-
2720
-    /**
2721
-     * set form open and close tags on add/edit pages.
2722
-     *
2723
-     * @access protected
2724
-     * @param string $route                    the route you want the form to direct to
2725
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
2726
-     * @return void
2727
-     */
2728
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
2729
-    {
2730
-        if (empty($route)) {
2731
-            $user_msg = __('An error occurred. No action was set for this page\'s form.', 'event_espresso');
2732
-            $dev_msg = $user_msg . "\n" . sprintf(__('The $route argument is required for the %s->%s method.', 'event_espresso'), __FUNCTION__, __CLASS__);
2733
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
2734
-        }
2735
-        // open form
2736
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="' . $this->_admin_base_url . '" id="' . $route . '_event_form" >';
2737
-        // add nonce
2738
-        $nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
2739
-        //		$nonce = wp_nonce_field( $route . '_nonce', '_wpnonce', FALSE, FALSE );
2740
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
2741
-        // add REQUIRED form action
2742
-        $hidden_fields = array(
2743
-                'action' => array('type' => 'hidden', 'value' => $route),
2744
-        );
2745
-        // merge arrays
2746
-        $hidden_fields = is_array($additional_hidden_fields) ? array_merge($hidden_fields, $additional_hidden_fields) : $hidden_fields;
2747
-        // generate form fields
2748
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
2749
-        // add fields to form
2750
-        foreach ((array)$form_fields as $field_name => $form_field) {
2751
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
2752
-        }
2753
-        // close form
2754
-        $this->_template_args['after_admin_page_content'] = '</form>';
2755
-    }
2756
-
2757
-
2758
-
2759
-    /**
2760
-     * Public Wrapper for _redirect_after_action() method since its
2761
-     * discovered it would be useful for external code to have access.
2762
-     *
2763
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
2764
-     * @since 4.5.0
2765
-     */
2766
-    public function redirect_after_action($success = false, $what = 'item', $action_desc = 'processed', $query_args = array(), $override_overwrite = false)
2767
-    {
2768
-        $this->_redirect_after_action($success, $what, $action_desc, $query_args, $override_overwrite);
2769
-    }
2770
-
2771
-
2772
-
2773
-    /**
2774
-     *    _redirect_after_action
2775
-     *
2776
-     * @param int    $success            - whether success was for two or more records, or just one, or none
2777
-     * @param string $what               - what the action was performed on
2778
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
2779
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin action is completed
2780
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to override this so that they show.
2781
-     * @access protected
2782
-     * @return void
2783
-     */
2784
-    protected function _redirect_after_action($success = 0, $what = 'item', $action_desc = 'processed', $query_args = array(), $override_overwrite = false)
2785
-    {
2786
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2787
-        //class name for actions/filters.
2788
-        $classname = get_class($this);
2789
-        //set redirect url. Note if there is a "page" index in the $query_args then we go with vanilla admin.php route, otherwise we go with whatever is set as the _admin_base_url
2790
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
2791
-        $notices = EE_Error::get_notices(false);
2792
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
2793
-        if ( ! $override_overwrite || ! empty($notices['errors'])) {
2794
-            EE_Error::overwrite_success();
2795
-        }
2796
-        if ( ! empty($what) && ! empty($action_desc)) {
2797
-            // how many records affected ? more than one record ? or just one ?
2798
-            if ($success > 1 && empty($notices['errors'])) {
2799
-                // set plural msg
2800
-                EE_Error::add_success(
2801
-                        sprintf(
2802
-                                __('The "%s" have been successfully %s.', 'event_espresso'),
2803
-                                $what,
2804
-                                $action_desc
2805
-                        ),
2806
-                        __FILE__, __FUNCTION__, __LINE__
2807
-                );
2808
-            } else if ($success == 1 && empty($notices['errors'])) {
2809
-                // set singular msg
2810
-                EE_Error::add_success(
2811
-                        sprintf(
2812
-                                __('The "%s" has been successfully %s.', 'event_espresso'),
2813
-                                $what,
2814
-                                $action_desc
2815
-                        ),
2816
-                        __FILE__, __FUNCTION__, __LINE__
2817
-                );
2818
-            }
2819
-        }
2820
-        // check that $query_args isn't something crazy
2821
-        if ( ! is_array($query_args)) {
2822
-            $query_args = array();
2823
-        }
2824
-        /**
2825
-         * Allow injecting actions before the query_args are modified for possible different
2826
-         * redirections on save and close actions
2827
-         *
2828
-         * @since 4.2.0
2829
-         * @param array $query_args       The original query_args array coming into the
2830
-         *                                method.
2831
-         */
2832
-        do_action('AHEE__' . $classname . '___redirect_after_action__before_redirect_modification_' . $this->_req_action, $query_args);
2833
-        //calculate where we're going (if we have a "save and close" button pushed)
2834
-        if (isset($this->_req_data['save_and_close']) && isset($this->_req_data['save_and_close_referrer'])) {
2835
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
2836
-            $parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
2837
-            // regenerate query args array from referrer URL
2838
-            parse_str($parsed_url['query'], $query_args);
2839
-            // correct page and action will be in the query args now
2840
-            $redirect_url = admin_url('admin.php');
2841
-        }
2842
-        //merge any default query_args set in _default_route_query_args property
2843
-        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
2844
-            $args_to_merge = array();
2845
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
2846
-                //is there a wp_referer array in our _default_route_query_args property?
2847
-                if ($query_param == 'wp_referer') {
2848
-                    $query_value = (array)$query_value;
2849
-                    foreach ($query_value as $reference => $value) {
2850
-                        if (strpos($reference, 'nonce') !== false) {
2851
-                            continue;
2852
-                        }
2853
-                        //finally we will override any arguments in the referer with
2854
-                        //what might be set on the _default_route_query_args array.
2855
-                        if (isset($this->_default_route_query_args[$reference])) {
2856
-                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
2857
-                        } else {
2858
-                            $args_to_merge[$reference] = urlencode($value);
2859
-                        }
2860
-                    }
2861
-                    continue;
2862
-                }
2863
-                $args_to_merge[$query_param] = $query_value;
2864
-            }
2865
-            //now let's merge these arguments but override with what was specifically sent in to the
2866
-            //redirect.
2867
-            $query_args = array_merge($args_to_merge, $query_args);
2868
-        }
2869
-        $this->_process_notices($query_args);
2870
-        // generate redirect url
2871
-        // if redirecting to anything other than the main page, add a nonce
2872
-        if (isset($query_args['action'])) {
2873
-            // manually generate wp_nonce and merge that with the query vars becuz the wp_nonce_url function wrecks havoc on some vars
2874
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
2875
-        }
2876
-        //we're adding some hooks and filters in here for processing any things just before redirects (example: an admin page has done an insert or update and we want to run something after that).
2877
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
2878
-        $redirect_url = apply_filters('FHEE_redirect_' . $classname . $this->_req_action, self::add_query_args_and_nonce($query_args, $redirect_url), $query_args);
2879
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
2880
-        if (defined('DOING_AJAX')) {
2881
-            $default_data = array(
2882
-                    'close'        => true,
2883
-                    'redirect_url' => $redirect_url,
2884
-                    'where'        => 'main',
2885
-                    'what'         => 'append',
2886
-            );
2887
-            $this->_template_args['success'] = $success;
2888
-            $this->_template_args['data'] = ! empty($this->_template_args['data']) ? array_merge($default_data, $this->_template_args['data']) : $default_data;
2889
-            $this->_return_json();
2890
-        }
2891
-        wp_safe_redirect($redirect_url);
2892
-        exit();
2893
-    }
2894
-
2895
-
2896
-
2897
-    /**
2898
-     * process any notices before redirecting (or returning ajax request)
2899
-     * This method sets the $this->_template_args['notices'] attribute;
2900
-     *
2901
-     * @param  array $query_args        any query args that need to be used for notice transient ('action')
2902
-     * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and page_routes haven't been defined yet.
2903
-     * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we still save a transient for the notice.
2904
-     * @return void
2905
-     */
2906
-    protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
2907
-    {
2908
-        //first let's set individual error properties if doing_ajax and the properties aren't already set.
2909
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2910
-            $notices = EE_Error::get_notices(false);
2911
-            if (empty($this->_template_args['success'])) {
2912
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
2913
-            }
2914
-            if (empty($this->_template_args['errors'])) {
2915
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
2916
-            }
2917
-            if (empty($this->_template_args['attention'])) {
2918
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
2919
-            }
2920
-        }
2921
-        $this->_template_args['notices'] = EE_Error::get_notices();
2922
-        //IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
2923
-        if ( ! defined('DOING_AJAX') || $sticky_notices) {
2924
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
2925
-            $this->_add_transient($route, $this->_template_args['notices'], true, $skip_route_verify);
2926
-        }
2927
-    }
2928
-
2929
-
2930
-
2931
-    /**
2932
-     * get_action_link_or_button
2933
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
2934
-     *
2935
-     * @param string $action        use this to indicate which action the url is generated with.
2936
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key) property.
2937
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
2938
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
2939
-     * @param string $base_url      If this is not provided
2940
-     *                              the _admin_base_url will be used as the default for the button base_url.
2941
-     *                              Otherwise this value will be used.
2942
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
2943
-     * @return string
2944
-     * @throws \EE_Error
2945
-     */
2946
-    public function get_action_link_or_button(
2947
-            $action,
2948
-            $type = 'add',
2949
-            $extra_request = array(),
2950
-            $class = 'button-primary',
2951
-            $base_url = '',
2952
-            $exclude_nonce = false
2953
-    ) {
2954
-        //first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
2955
-        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
2956
-            throw new EE_Error(
2957
-                    sprintf(
2958
-                            __(
2959
-                                    'There is no page route for given action for the button.  This action was given: %s',
2960
-                                    'event_espresso'
2961
-                            ),
2962
-                            $action
2963
-                    )
2964
-            );
2965
-        }
2966
-        if ( ! isset($this->_labels['buttons'][$type])) {
2967
-            throw new EE_Error(
2968
-                    sprintf(
2969
-                            __(
2970
-                                    'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
2971
-                                    'event_espresso'
2972
-                            ),
2973
-                            $type
2974
-                    )
2975
-            );
2976
-        }
2977
-        //finally check user access for this button.
2978
-        $has_access = $this->check_user_access($action, true);
2979
-        if ( ! $has_access) {
2980
-            return '';
2981
-        }
2982
-        $_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
2983
-        $query_args = array(
2984
-                'action' => $action,
2985
-        );
2986
-        //merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
2987
-        if ( ! empty($extra_request)) {
2988
-            $query_args = array_merge($extra_request, $query_args);
2989
-        }
2990
-        $url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
2991
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
2992
-    }
2993
-
2994
-
2995
-
2996
-    /**
2997
-     * _per_page_screen_option
2998
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
2999
-     *
3000
-     * @return void
3001
-     */
3002
-    protected function _per_page_screen_option()
3003
-    {
3004
-        $option = 'per_page';
3005
-        $args = array(
3006
-                'label'   => $this->_admin_page_title,
3007
-                'default' => 10,
3008
-                'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3009
-        );
3010
-        //ONLY add the screen option if the user has access to it.
3011
-        if ($this->check_user_access($this->_current_view, true)) {
3012
-            add_screen_option($option, $args);
3013
-        }
3014
-    }
3015
-
3016
-
3017
-
3018
-    /**
3019
-     * set_per_page_screen_option
3020
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3021
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than admin_menu.
3022
-     *
3023
-     * @access private
3024
-     * @return void
3025
-     */
3026
-    private function _set_per_page_screen_options()
3027
-    {
3028
-        if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3029
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3030
-            if ( ! $user = wp_get_current_user()) {
3031
-                return;
3032
-            }
3033
-            $option = $_POST['wp_screen_options']['option'];
3034
-            $value = $_POST['wp_screen_options']['value'];
3035
-            if ($option != sanitize_key($option)) {
3036
-                return;
3037
-            }
3038
-            $map_option = $option;
3039
-            $option = str_replace('-', '_', $option);
3040
-            switch ($map_option) {
3041
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3042
-                    $value = (int)$value;
3043
-                    if ($value < 1 || $value > 999) {
3044
-                        return;
3045
-                    }
3046
-                    break;
3047
-                default:
3048
-                    $value = apply_filters('FHEE__EE_Admin_Page___set_per_page_screen_options__value', false, $option, $value);
3049
-                    if (false === $value) {
3050
-                        return;
3051
-                    }
3052
-                    break;
3053
-            }
3054
-            update_user_meta($user->ID, $option, $value);
3055
-            wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3056
-            exit;
3057
-        }
3058
-    }
3059
-
3060
-
3061
-
3062
-    /**
3063
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3064
-     *
3065
-     * @param array $data array that will be assigned to template args.
3066
-     */
3067
-    public function set_template_args($data)
3068
-    {
3069
-        $this->_template_args = array_merge($this->_template_args, (array)$data);
3070
-    }
3071
-
3072
-
3073
-
3074
-    /**
3075
-     * This makes available the WP transient system for temporarily moving data between routes
3076
-     *
3077
-     * @access protected
3078
-     * @param string $route             the route that should receive the transient
3079
-     * @param array  $data              the data that gets sent
3080
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a normal route transient.
3081
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used when we are adding a transient before page_routes have been defined.
3082
-     * @return void
3083
-     */
3084
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3085
-    {
3086
-        $user_id = get_current_user_id();
3087
-        if ( ! $skip_route_verify) {
3088
-            $this->_verify_route($route);
3089
-        }
3090
-        //now let's set the string for what kind of transient we're setting
3091
-        $transient = $notices ? 'ee_rte_n_tx_' . $route . '_' . $user_id : 'rte_tx_' . $route . '_' . $user_id;
3092
-        $data = $notices ? array('notices' => $data) : $data;
3093
-        //is there already a transient for this route?  If there is then let's ADD to that transient
3094
-        $existing = is_multisite() && is_network_admin() ? get_site_transient($transient) : get_transient($transient);
3095
-        if ($existing) {
3096
-            $data = array_merge((array)$data, (array)$existing);
3097
-        }
3098
-        if (is_multisite() && is_network_admin()) {
3099
-            set_site_transient($transient, $data, 8);
3100
-        } else {
3101
-            set_transient($transient, $data, 8);
3102
-        }
3103
-    }
3104
-
3105
-
3106
-
3107
-    /**
3108
-     * this retrieves the temporary transient that has been set for moving data between routes.
3109
-     *
3110
-     * @param bool $notices true we get notices transient. False we just return normal route transient
3111
-     * @return mixed data
3112
-     */
3113
-    protected function _get_transient($notices = false, $route = false)
3114
-    {
3115
-        $user_id = get_current_user_id();
3116
-        $route = ! $route ? $this->_req_action : $route;
3117
-        $transient = $notices ? 'ee_rte_n_tx_' . $route . '_' . $user_id : 'rte_tx_' . $route . '_' . $user_id;
3118
-        $data = is_multisite() && is_network_admin() ? get_site_transient($transient) : get_transient($transient);
3119
-        //delete transient after retrieval (just in case it hasn't expired);
3120
-        if (is_multisite() && is_network_admin()) {
3121
-            delete_site_transient($transient);
3122
-        } else {
3123
-            delete_transient($transient);
3124
-        }
3125
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3126
-    }
3127
-
3128
-
3129
-
3130
-    /**
3131
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but would not be called later.
3132
-     * This will be assigned to run on a specific EE Admin page. (place the method in the default route callback on the EE_Admin page you want it run.)
3133
-     *
3134
-     * @return void
3135
-     */
3136
-    protected function _transient_garbage_collection()
3137
-    {
3138
-        global $wpdb;
3139
-        //retrieve all existing transients
3140
-        $query = "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3141
-        if ($results = $wpdb->get_results($query)) {
3142
-            foreach ($results as $result) {
3143
-                $transient = str_replace('_transient_', '', $result->option_name);
3144
-                get_transient($transient);
3145
-                if (is_multisite() && is_network_admin()) {
3146
-                    get_site_transient($transient);
3147
-                }
3148
-            }
3149
-        }
3150
-    }
3151
-
3152
-
3153
-
3154
-    /**
3155
-     * get_view
3156
-     *
3157
-     * @access public
3158
-     * @return string content of _view property
3159
-     */
3160
-    public function get_view()
3161
-    {
3162
-        return $this->_view;
3163
-    }
3164
-
3165
-
3166
-
3167
-    /**
3168
-     * getter for the protected $_views property
3169
-     *
3170
-     * @return array
3171
-     */
3172
-    public function get_views()
3173
-    {
3174
-        return $this->_views;
3175
-    }
3176
-
3177
-
3178
-
3179
-    /**
3180
-     * get_current_page
3181
-     *
3182
-     * @access public
3183
-     * @return string _current_page property value
3184
-     */
3185
-    public function get_current_page()
3186
-    {
3187
-        return $this->_current_page;
3188
-    }
3189
-
3190
-
3191
-
3192
-    /**
3193
-     * get_current_view
3194
-     *
3195
-     * @access public
3196
-     * @return string _current_view property value
3197
-     */
3198
-    public function get_current_view()
3199
-    {
3200
-        return $this->_current_view;
3201
-    }
3202
-
3203
-
3204
-
3205
-    /**
3206
-     * get_current_screen
3207
-     *
3208
-     * @access public
3209
-     * @return object The current WP_Screen object
3210
-     */
3211
-    public function get_current_screen()
3212
-    {
3213
-        return $this->_current_screen;
3214
-    }
3215
-
3216
-
3217
-
3218
-    /**
3219
-     * get_current_page_view_url
3220
-     *
3221
-     * @access public
3222
-     * @return string This returns the url for the current_page_view.
3223
-     */
3224
-    public function get_current_page_view_url()
3225
-    {
3226
-        return $this->_current_page_view_url;
3227
-    }
3228
-
3229
-
3230
-
3231
-    /**
3232
-     * just returns the _req_data property
3233
-     *
3234
-     * @return array
3235
-     */
3236
-    public function get_request_data()
3237
-    {
3238
-        return $this->_req_data;
3239
-    }
3240
-
3241
-
3242
-
3243
-    /**
3244
-     * returns the _req_data protected property
3245
-     *
3246
-     * @return string
3247
-     */
3248
-    public function get_req_action()
3249
-    {
3250
-        return $this->_req_action;
3251
-    }
3252
-
3253
-
3254
-
3255
-    /**
3256
-     * @return bool  value of $_is_caf property
3257
-     */
3258
-    public function is_caf()
3259
-    {
3260
-        return $this->_is_caf;
3261
-    }
3262
-
3263
-
3264
-
3265
-    /**
3266
-     * @return mixed
3267
-     */
3268
-    public function default_espresso_metaboxes()
3269
-    {
3270
-        return $this->_default_espresso_metaboxes;
3271
-    }
3272
-
3273
-
3274
-
3275
-    /**
3276
-     * @return mixed
3277
-     */
3278
-    public function admin_base_url()
3279
-    {
3280
-        return $this->_admin_base_url;
3281
-    }
3282
-
3283
-
3284
-
3285
-    /**
3286
-     * @return mixed
3287
-     */
3288
-    public function wp_page_slug()
3289
-    {
3290
-        return $this->_wp_page_slug;
3291
-    }
3292
-
3293
-
3294
-
3295
-    /**
3296
-     * updates  espresso configuration settings
3297
-     *
3298
-     * @access    protected
3299
-     * @param string                   $tab
3300
-     * @param EE_Config_Base|EE_Config $config
3301
-     * @param string                   $file file where error occurred
3302
-     * @param string                   $func function  where error occurred
3303
-     * @param string                   $line line no where error occurred
3304
-     * @return boolean
3305
-     */
3306
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3307
-    {
3308
-        //remove any options that are NOT going to be saved with the config settings.
3309
-        if (isset($config->core->ee_ueip_optin)) {
3310
-            $config->core->ee_ueip_has_notified = true;
3311
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
3312
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3313
-            update_option('ee_ueip_has_notified', true);
3314
-        }
3315
-        // and save it (note we're also doing the network save here)
3316
-        $net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
3317
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
3318
-        if ($config_saved && $net_saved) {
3319
-            EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3320
-            return true;
3321
-        } else {
3322
-            EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3323
-            return false;
3324
-        }
3325
-    }
3326
-
3327
-
3328
-
3329
-    /**
3330
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
3331
-     *
3332
-     * @return array
3333
-     */
3334
-    public function get_yes_no_values()
3335
-    {
3336
-        return $this->_yes_no_values;
3337
-    }
3338
-
3339
-
3340
-
3341
-    protected function _get_dir()
3342
-    {
3343
-        $reflector = new ReflectionClass(get_class($this));
3344
-        return dirname($reflector->getFileName());
3345
-    }
3346
-
3347
-
3348
-
3349
-    /**
3350
-     * A helper for getting a "next link".
3351
-     *
3352
-     * @param string $url   The url to link to
3353
-     * @param string $class The class to use.
3354
-     * @return string
3355
-     */
3356
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
3357
-    {
3358
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
3359
-    }
3360
-
3361
-
3362
-
3363
-    /**
3364
-     * A helper for getting a "previous link".
3365
-     *
3366
-     * @param string $url   The url to link to
3367
-     * @param string $class The class to use.
3368
-     * @return string
3369
-     */
3370
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
3371
-    {
3372
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
3373
-    }
3374
-
3375
-
3376
-
3377
-
3378
-
3379
-
3380
-
3381
-    //below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
3382
-    /**
3383
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the _req_data
3384
-     * array.
3385
-     *
3386
-     * @return bool success/fail
3387
-     */
3388
-    protected function _process_resend_registration()
3389
-    {
3390
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
3391
-        do_action('AHEE__EE_Admin_Page___process_resend_registration', $this->_template_args['success'], $this->_req_data);
3392
-        return $this->_template_args['success'];
3393
-    }
3394
-
3395
-
3396
-
3397
-    /**
3398
-     * This automatically processes any payment message notifications when manual payment has been applied.
3399
-     *
3400
-     * @access protected
3401
-     * @param \EE_Payment $payment
3402
-     * @return bool success/fail
3403
-     */
3404
-    protected function _process_payment_notification(EE_Payment $payment)
3405
-    {
3406
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
3407
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
3408
-        $this->_template_args['success'] = apply_filters('FHEE__EE_Admin_Page___process_admin_payment_notification__success', false, $payment);
3409
-        return $this->_template_args['success'];
3410
-    }
2196
+	}
2197
+
2198
+
2199
+
2200
+	/**
2201
+	 * facade for add_meta_box
2202
+	 *
2203
+	 * @param string  $action        where the metabox get's displayed
2204
+	 * @param string  $title         Title of Metabox (output in metabox header)
2205
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback instead of the one created in here.
2206
+	 * @param array   $callback_args an array of args supplied for the metabox
2207
+	 * @param string  $column        what metabox column
2208
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2209
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function created but just set our own callback for wp's add_meta_box.
2210
+	 */
2211
+	public function _add_admin_page_meta_box($action, $title, $callback, $callback_args, $column = 'normal', $priority = 'high', $create_func = true)
2212
+	{
2213
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2214
+		//if we have empty callback args and we want to automatically create the metabox callback then we need to make sure the callback args are generated.
2215
+		if (empty($callback_args) && $create_func) {
2216
+			$callback_args = array(
2217
+					'template_path' => $this->_template_path,
2218
+					'template_args' => $this->_template_args,
2219
+			);
2220
+		}
2221
+		//if $create_func is true (default) then we automatically create the function for displaying the actual meta box.  If false then we take the $callback reference passed through and use it instead (so callers can define their own callback function/method if they wish)
2222
+		$call_back_func = $create_func ? create_function('$post, $metabox',
2223
+				'do_action( "AHEE_log", __FILE__, __FUNCTION__, ""); echo EEH_Template::display_template( $metabox["args"]["template_path"], $metabox["args"]["template_args"], TRUE );') : $callback;
2224
+		add_meta_box(str_replace('_', '-', $action) . '-mbox', $title, $call_back_func, $this->_wp_page_slug, $column, $priority, $callback_args);
2225
+	}
2226
+
2227
+
2228
+
2229
+	/**
2230
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2231
+	 *
2232
+	 * @return [type] [description]
2233
+	 */
2234
+	public function display_admin_page_with_metabox_columns()
2235
+	{
2236
+		$this->_template_args['post_body_content'] = $this->_template_args['admin_page_content'];
2237
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($this->_column_template_path, $this->_template_args, true);
2238
+		//the final wrapper
2239
+		$this->admin_page_wrapper();
2240
+	}
2241
+
2242
+
2243
+
2244
+	/**
2245
+	 *        generates  HTML wrapper for an admin details page
2246
+	 *
2247
+	 * @access public
2248
+	 * @return void
2249
+	 */
2250
+	public function display_admin_page_with_sidebar()
2251
+	{
2252
+		$this->_display_admin_page(true);
2253
+	}
2254
+
2255
+
2256
+
2257
+	/**
2258
+	 *        generates  HTML wrapper for an admin details page (except no sidebar)
2259
+	 *
2260
+	 * @access public
2261
+	 * @return void
2262
+	 */
2263
+	public function display_admin_page_with_no_sidebar()
2264
+	{
2265
+		$this->_display_admin_page();
2266
+	}
2267
+
2268
+
2269
+
2270
+	/**
2271
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2272
+	 *
2273
+	 * @access public
2274
+	 * @return void
2275
+	 */
2276
+	public function display_about_admin_page()
2277
+	{
2278
+		$this->_display_admin_page(false, true);
2279
+	}
2280
+
2281
+
2282
+
2283
+	/**
2284
+	 * display_admin_page
2285
+	 * contains the code for actually displaying an admin page
2286
+	 *
2287
+	 * @access private
2288
+	 * @param  boolean $sidebar true with sidebar, false without
2289
+	 * @param  boolean $about   use the about admin wrapper instead of the default.
2290
+	 * @return void
2291
+	 */
2292
+	private function _display_admin_page($sidebar = false, $about = false)
2293
+	{
2294
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2295
+		//custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2296
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2297
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2298
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2299
+		$this->_template_args['current_page'] = $this->_wp_page_slug;
2300
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2301
+				? 'poststuff'
2302
+				: 'espresso-default-admin';
2303
+		$template_path = $sidebar
2304
+				? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2305
+				: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2306
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2307
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2308
+		}
2309
+		$template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2310
+		$this->_template_args['post_body_content'] = isset($this->_template_args['admin_page_content']) ? $this->_template_args['admin_page_content'] : '';
2311
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content']) ? $this->_template_args['before_admin_page_content'] : '';
2312
+		$this->_template_args['after_admin_page_content'] = isset($this->_template_args['after_admin_page_content']) ? $this->_template_args['after_admin_page_content'] : '';
2313
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path, $this->_template_args, true);
2314
+		// the final template wrapper
2315
+		$this->admin_page_wrapper($about);
2316
+	}
2317
+
2318
+
2319
+
2320
+	/**
2321
+	 * This is used to display caf preview pages.
2322
+	 *
2323
+	 * @since 4.3.2
2324
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2325
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2326
+	 * @return void
2327
+	 * @throws \EE_Error
2328
+	 */
2329
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2330
+	{
2331
+		//let's generate a default preview action button if there isn't one already present.
2332
+		$this->_labels['buttons']['buy_now'] = __('Upgrade to Event Espresso 4 Right Now', 'event_espresso');
2333
+		$buy_now_url = add_query_arg(
2334
+				array(
2335
+						'ee_ver'       => 'ee4',
2336
+						'utm_source'   => 'ee4_plugin_admin',
2337
+						'utm_medium'   => 'link',
2338
+						'utm_campaign' => $utm_campaign_source,
2339
+						'utm_content'  => 'buy_now_button',
2340
+				),
2341
+				'http://eventespresso.com/pricing/'
2342
+		);
2343
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2344
+				? $this->get_action_link_or_button(
2345
+						'',
2346
+						'buy_now',
2347
+						array(),
2348
+						'button-primary button-large',
2349
+						$buy_now_url,
2350
+						true
2351
+				)
2352
+				: $this->_template_args['preview_action_button'];
2353
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php';
2354
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2355
+				$template_path,
2356
+				$this->_template_args,
2357
+				true
2358
+		);
2359
+		$this->_display_admin_page($display_sidebar);
2360
+	}
2361
+
2362
+
2363
+
2364
+	/**
2365
+	 * display_admin_list_table_page_with_sidebar
2366
+	 * generates HTML wrapper for an admin_page with list_table
2367
+	 *
2368
+	 * @access public
2369
+	 * @return void
2370
+	 */
2371
+	public function display_admin_list_table_page_with_sidebar()
2372
+	{
2373
+		$this->_display_admin_list_table_page(true);
2374
+	}
2375
+
2376
+
2377
+
2378
+	/**
2379
+	 * display_admin_list_table_page_with_no_sidebar
2380
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2381
+	 *
2382
+	 * @access public
2383
+	 * @return void
2384
+	 */
2385
+	public function display_admin_list_table_page_with_no_sidebar()
2386
+	{
2387
+		$this->_display_admin_list_table_page();
2388
+	}
2389
+
2390
+
2391
+
2392
+	/**
2393
+	 * generates html wrapper for an admin_list_table page
2394
+	 *
2395
+	 * @access private
2396
+	 * @param boolean $sidebar whether to display with sidebar or not.
2397
+	 * @return void
2398
+	 */
2399
+	private function _display_admin_list_table_page($sidebar = false)
2400
+	{
2401
+		//setup search attributes
2402
+		$this->_set_search_attributes();
2403
+		$this->_template_args['current_page'] = $this->_wp_page_slug;
2404
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2405
+		$this->_template_args['table_url'] = defined('DOING_AJAX')
2406
+				? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2407
+				: add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
2408
+		$this->_template_args['list_table'] = $this->_list_table_object;
2409
+		$this->_template_args['current_route'] = $this->_req_action;
2410
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2411
+		$ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2412
+		if ( ! empty($ajax_sorting_callback)) {
2413
+			$sortable_list_table_form_fields = wp_nonce_field(
2414
+					$ajax_sorting_callback . '_nonce',
2415
+					$ajax_sorting_callback . '_nonce',
2416
+					false,
2417
+					false
2418
+			);
2419
+			//			$reorder_action = 'espresso_' . $ajax_sorting_callback . '_nonce';
2420
+			//			$sortable_list_table_form_fields = wp_nonce_field( $reorder_action, 'ajax_table_sort_nonce', FALSE, FALSE );
2421
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="' . $this->page_slug . '" />';
2422
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="' . $ajax_sorting_callback . '" />';
2423
+		} else {
2424
+			$sortable_list_table_form_fields = '';
2425
+		}
2426
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2427
+		$hidden_form_fields = isset($this->_template_args['list_table_hidden_fields']) ? $this->_template_args['list_table_hidden_fields'] : '';
2428
+		$nonce_ref = $this->_req_action . '_nonce';
2429
+		$hidden_form_fields .= '<input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2430
+		$this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2431
+		//display message about search results?
2432
+		$this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
2433
+				? '<p class="ee-search-results">' . sprintf(
2434
+						esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2435
+						trim($this->_req_data['s'], '%')
2436
+				) . '</p>'
2437
+				: '';
2438
+		// filter before_list_table template arg
2439
+		$this->_template_args['before_list_table'] = apply_filters(
2440
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2441
+			$this->_template_args['before_list_table'],
2442
+			$this->page_slug,
2443
+			$this->_req_data,
2444
+			$this->_req_action
2445
+		);
2446
+		// convert to array and filter again
2447
+		// arrays are easier to inject new items in a specific location,
2448
+		// but would not be backwards compatible, so we have to add a new filter
2449
+		$this->_template_args['before_list_table'] = implode(
2450
+			" \n",
2451
+			(array) apply_filters(
2452
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2453
+				(array) $this->_template_args['before_list_table'],
2454
+				$this->page_slug,
2455
+				$this->_req_data,
2456
+				$this->_req_action
2457
+			)
2458
+		);
2459
+		// filter after_list_table template arg
2460
+		$this->_template_args['after_list_table'] = apply_filters(
2461
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2462
+			$this->_template_args['after_list_table'],
2463
+			$this->page_slug,
2464
+			$this->_req_data,
2465
+			$this->_req_action
2466
+		);
2467
+		// convert to array and filter again
2468
+		// arrays are easier to inject new items in a specific location,
2469
+		// but would not be backwards compatible, so we have to add a new filter
2470
+		$this->_template_args['after_list_table'] = implode(
2471
+			" \n",
2472
+			(array) apply_filters(
2473
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
2474
+				(array) $this->_template_args['after_list_table'],
2475
+				$this->page_slug,
2476
+				$this->_req_data,
2477
+				$this->_req_action
2478
+			)
2479
+		);
2480
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2481
+				$template_path,
2482
+				$this->_template_args,
2483
+				true
2484
+		);
2485
+		// the final template wrapper
2486
+		if ($sidebar) {
2487
+			$this->display_admin_page_with_sidebar();
2488
+		} else {
2489
+			$this->display_admin_page_with_no_sidebar();
2490
+		}
2491
+	}
2492
+
2493
+
2494
+
2495
+	/**
2496
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the html string for the legend.
2497
+	 * $items are expected in an array in the following format:
2498
+	 * $legend_items = array(
2499
+	 *        'item_id' => array(
2500
+	 *            'icon' => 'http://url_to_icon_being_described.png',
2501
+	 *            'desc' => __('localized description of item');
2502
+	 *        )
2503
+	 * );
2504
+	 *
2505
+	 * @param  array $items see above for format of array
2506
+	 * @return string        html string of legend
2507
+	 */
2508
+	protected function _display_legend($items)
2509
+	{
2510
+		$this->_template_args['items'] = apply_filters('FHEE__EE_Admin_Page___display_legend__items', (array)$items, $this);
2511
+		$legend_template = EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php';
2512
+		return EEH_Template::display_template($legend_template, $this->_template_args, true);
2513
+	}
2514
+
2515
+
2516
+	/**
2517
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
2518
+	 * The returned json object is created from an array in the following format:
2519
+	 * array(
2520
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
2521
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
2522
+	 *  'notices' => '', // - contains any EE_Error formatted notices
2523
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
2524
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js. We're also going to include the template args with every package (so js can pick out any
2525
+	 *  specific template args that might be included in here)
2526
+	 * )
2527
+	 * The json object is populated by whatever is set in the $_template_args property.
2528
+	 *
2529
+	 * @param bool  $sticky_notices Used to indicate whether you want to ensure notices are added to a transient instead of displayed.
2530
+	 * @param array $notices_arguments  Use this to pass any additional args on to the _process_notices.
2531
+	 * @return void
2532
+	 */
2533
+	protected function _return_json($sticky_notices = false, $notices_arguments = array())
2534
+	{
2535
+		//make sure any EE_Error notices have been handled.
2536
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
2537
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
2538
+		unset($this->_template_args['data']);
2539
+		$json = array(
2540
+				'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
2541
+				'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
2542
+				'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
2543
+				'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
2544
+				'notices'   => EE_Error::get_notices(),
2545
+				'content'   => isset($this->_template_args['admin_page_content']) ? $this->_template_args['admin_page_content'] : '',
2546
+				'data'      => array_merge($data, array('template_args' => $this->_template_args)),
2547
+				'isEEajax'  => true //special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
2548
+		);
2549
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
2550
+		if (null === error_get_last() || ! headers_sent()) {
2551
+			header('Content-Type: application/json; charset=UTF-8');
2552
+		}
2553
+		echo wp_json_encode($json);
2554
+
2555
+		exit();
2556
+	}
2557
+
2558
+
2559
+
2560
+	/**
2561
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
2562
+	 *
2563
+	 * @return void
2564
+	 * @throws EE_Error
2565
+	 */
2566
+	public function return_json()
2567
+	{
2568
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2569
+			$this->_return_json();
2570
+		} else {
2571
+			throw new EE_Error(sprintf(__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'), __FUNCTION__));
2572
+		}
2573
+	}
2574
+
2575
+
2576
+
2577
+	/**
2578
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
2579
+	 *
2580
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
2581
+	 * @access   public
2582
+	 */
2583
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
2584
+	{
2585
+		$this->_hook_obj = $hook_obj;
2586
+	}
2587
+
2588
+
2589
+
2590
+	/**
2591
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
2592
+	 *
2593
+	 * @access public
2594
+	 * @param  boolean $about whether to use the special about page wrapper or default.
2595
+	 * @return void
2596
+	 */
2597
+	public function admin_page_wrapper($about = false)
2598
+	{
2599
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2600
+		$this->_nav_tabs = $this->_get_main_nav_tabs();
2601
+		$this->_template_args['nav_tabs'] = $this->_nav_tabs;
2602
+		$this->_template_args['admin_page_title'] = $this->_admin_page_title;
2603
+		$this->_template_args['before_admin_page_content'] = apply_filters('FHEE_before_admin_page_content' . $this->_current_page . $this->_current_view,
2604
+				isset($this->_template_args['before_admin_page_content']) ? $this->_template_args['before_admin_page_content'] : '');
2605
+		$this->_template_args['after_admin_page_content'] = apply_filters('FHEE_after_admin_page_content' . $this->_current_page . $this->_current_view,
2606
+				isset($this->_template_args['after_admin_page_content']) ? $this->_template_args['after_admin_page_content'] : '');
2607
+		$this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
2608
+		// load settings page wrapper template
2609
+		$template_path = ! defined('DOING_AJAX') ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php' : EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php';
2610
+		//about page?
2611
+		$template_path = $about ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php' : $template_path;
2612
+		if (defined('DOING_AJAX')) {
2613
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template($template_path, $this->_template_args, true);
2614
+			$this->_return_json();
2615
+		} else {
2616
+			EEH_Template::display_template($template_path, $this->_template_args);
2617
+		}
2618
+	}
2619
+
2620
+
2621
+
2622
+	/**
2623
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
2624
+	 *
2625
+	 * @return string html
2626
+	 */
2627
+	protected function _get_main_nav_tabs()
2628
+	{
2629
+		//let's generate the html using the EEH_Tabbed_Content helper.  We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute (rather than setting in the page_routes array)
2630
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
2631
+	}
2632
+
2633
+
2634
+
2635
+	/**
2636
+	 *        sort nav tabs
2637
+	 *
2638
+	 * @access public
2639
+	 * @param $a
2640
+	 * @param $b
2641
+	 * @return int
2642
+	 */
2643
+	private function _sort_nav_tabs($a, $b)
2644
+	{
2645
+		if ($a['order'] == $b['order']) {
2646
+			return 0;
2647
+		}
2648
+		return ($a['order'] < $b['order']) ? -1 : 1;
2649
+	}
2650
+
2651
+
2652
+
2653
+	/**
2654
+	 *    generates HTML for the forms used on admin pages
2655
+	 *
2656
+	 * @access protected
2657
+	 * @param    array $input_vars - array of input field details
2658
+	 * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to use)
2659
+	 * @return string
2660
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
2661
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
2662
+	 */
2663
+	protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
2664
+	{
2665
+		$content = $generator == 'string' ? EEH_Form_Fields::get_form_fields($input_vars, $id) : EEH_Form_Fields::get_form_fields_array($input_vars);
2666
+		return $content;
2667
+	}
2668
+
2669
+
2670
+
2671
+	/**
2672
+	 * generates the "Save" and "Save & Close" buttons for edit forms
2673
+	 *
2674
+	 * @access protected
2675
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save & Close" button.
2676
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] => 'Save', [1] => 'save & close')
2677
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e. via the "name" value in the button).  We can also use this to just dump default actions by submitting some other value.
2678
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it will use the $referrer string. IF null, then we don't do ANYTHING on save and close (normal form handling).
2679
+	 */
2680
+	protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
2681
+	{
2682
+		//make sure $text and $actions are in an array
2683
+		$text = (array)$text;
2684
+		$actions = (array)$actions;
2685
+		$referrer_url = empty($referrer) ? '' : $referrer;
2686
+		$referrer_url = ! $referrer ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="' . $_SERVER['REQUEST_URI'] . '" />'
2687
+				: '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="' . $referrer . '" />';
2688
+		$button_text = ! empty($text) ? $text : array(__('Save', 'event_espresso'), __('Save and Close', 'event_espresso'));
2689
+		$default_names = array('save', 'save_and_close');
2690
+		//add in a hidden index for the current page (so save and close redirects properly)
2691
+		$this->_template_args['save_buttons'] = $referrer_url;
2692
+		foreach ($button_text as $key => $button) {
2693
+			$ref = $default_names[$key];
2694
+			$id = $this->_current_view . '_' . $ref;
2695
+			$name = ! empty($actions) ? $actions[$key] : $ref;
2696
+			$this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary ' . $ref . '" value="' . $button . '" name="' . $name . '" id="' . $id . '" />';
2697
+			if ( ! $both) {
2698
+				break;
2699
+			}
2700
+		}
2701
+	}
2702
+
2703
+
2704
+
2705
+	/**
2706
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
2707
+	 *
2708
+	 * @see   $this->_set_add_edit_form_tags() for details on params
2709
+	 * @since 4.6.0
2710
+	 * @param string $route
2711
+	 * @param array  $additional_hidden_fields
2712
+	 */
2713
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
2714
+	{
2715
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
2716
+	}
2717
+
2718
+
2719
+
2720
+	/**
2721
+	 * set form open and close tags on add/edit pages.
2722
+	 *
2723
+	 * @access protected
2724
+	 * @param string $route                    the route you want the form to direct to
2725
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
2726
+	 * @return void
2727
+	 */
2728
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
2729
+	{
2730
+		if (empty($route)) {
2731
+			$user_msg = __('An error occurred. No action was set for this page\'s form.', 'event_espresso');
2732
+			$dev_msg = $user_msg . "\n" . sprintf(__('The $route argument is required for the %s->%s method.', 'event_espresso'), __FUNCTION__, __CLASS__);
2733
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
2734
+		}
2735
+		// open form
2736
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="' . $this->_admin_base_url . '" id="' . $route . '_event_form" >';
2737
+		// add nonce
2738
+		$nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
2739
+		//		$nonce = wp_nonce_field( $route . '_nonce', '_wpnonce', FALSE, FALSE );
2740
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
2741
+		// add REQUIRED form action
2742
+		$hidden_fields = array(
2743
+				'action' => array('type' => 'hidden', 'value' => $route),
2744
+		);
2745
+		// merge arrays
2746
+		$hidden_fields = is_array($additional_hidden_fields) ? array_merge($hidden_fields, $additional_hidden_fields) : $hidden_fields;
2747
+		// generate form fields
2748
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
2749
+		// add fields to form
2750
+		foreach ((array)$form_fields as $field_name => $form_field) {
2751
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
2752
+		}
2753
+		// close form
2754
+		$this->_template_args['after_admin_page_content'] = '</form>';
2755
+	}
2756
+
2757
+
2758
+
2759
+	/**
2760
+	 * Public Wrapper for _redirect_after_action() method since its
2761
+	 * discovered it would be useful for external code to have access.
2762
+	 *
2763
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
2764
+	 * @since 4.5.0
2765
+	 */
2766
+	public function redirect_after_action($success = false, $what = 'item', $action_desc = 'processed', $query_args = array(), $override_overwrite = false)
2767
+	{
2768
+		$this->_redirect_after_action($success, $what, $action_desc, $query_args, $override_overwrite);
2769
+	}
2770
+
2771
+
2772
+
2773
+	/**
2774
+	 *    _redirect_after_action
2775
+	 *
2776
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
2777
+	 * @param string $what               - what the action was performed on
2778
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
2779
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin action is completed
2780
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to override this so that they show.
2781
+	 * @access protected
2782
+	 * @return void
2783
+	 */
2784
+	protected function _redirect_after_action($success = 0, $what = 'item', $action_desc = 'processed', $query_args = array(), $override_overwrite = false)
2785
+	{
2786
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2787
+		//class name for actions/filters.
2788
+		$classname = get_class($this);
2789
+		//set redirect url. Note if there is a "page" index in the $query_args then we go with vanilla admin.php route, otherwise we go with whatever is set as the _admin_base_url
2790
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
2791
+		$notices = EE_Error::get_notices(false);
2792
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
2793
+		if ( ! $override_overwrite || ! empty($notices['errors'])) {
2794
+			EE_Error::overwrite_success();
2795
+		}
2796
+		if ( ! empty($what) && ! empty($action_desc)) {
2797
+			// how many records affected ? more than one record ? or just one ?
2798
+			if ($success > 1 && empty($notices['errors'])) {
2799
+				// set plural msg
2800
+				EE_Error::add_success(
2801
+						sprintf(
2802
+								__('The "%s" have been successfully %s.', 'event_espresso'),
2803
+								$what,
2804
+								$action_desc
2805
+						),
2806
+						__FILE__, __FUNCTION__, __LINE__
2807
+				);
2808
+			} else if ($success == 1 && empty($notices['errors'])) {
2809
+				// set singular msg
2810
+				EE_Error::add_success(
2811
+						sprintf(
2812
+								__('The "%s" has been successfully %s.', 'event_espresso'),
2813
+								$what,
2814
+								$action_desc
2815
+						),
2816
+						__FILE__, __FUNCTION__, __LINE__
2817
+				);
2818
+			}
2819
+		}
2820
+		// check that $query_args isn't something crazy
2821
+		if ( ! is_array($query_args)) {
2822
+			$query_args = array();
2823
+		}
2824
+		/**
2825
+		 * Allow injecting actions before the query_args are modified for possible different
2826
+		 * redirections on save and close actions
2827
+		 *
2828
+		 * @since 4.2.0
2829
+		 * @param array $query_args       The original query_args array coming into the
2830
+		 *                                method.
2831
+		 */
2832
+		do_action('AHEE__' . $classname . '___redirect_after_action__before_redirect_modification_' . $this->_req_action, $query_args);
2833
+		//calculate where we're going (if we have a "save and close" button pushed)
2834
+		if (isset($this->_req_data['save_and_close']) && isset($this->_req_data['save_and_close_referrer'])) {
2835
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
2836
+			$parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
2837
+			// regenerate query args array from referrer URL
2838
+			parse_str($parsed_url['query'], $query_args);
2839
+			// correct page and action will be in the query args now
2840
+			$redirect_url = admin_url('admin.php');
2841
+		}
2842
+		//merge any default query_args set in _default_route_query_args property
2843
+		if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
2844
+			$args_to_merge = array();
2845
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
2846
+				//is there a wp_referer array in our _default_route_query_args property?
2847
+				if ($query_param == 'wp_referer') {
2848
+					$query_value = (array)$query_value;
2849
+					foreach ($query_value as $reference => $value) {
2850
+						if (strpos($reference, 'nonce') !== false) {
2851
+							continue;
2852
+						}
2853
+						//finally we will override any arguments in the referer with
2854
+						//what might be set on the _default_route_query_args array.
2855
+						if (isset($this->_default_route_query_args[$reference])) {
2856
+							$args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
2857
+						} else {
2858
+							$args_to_merge[$reference] = urlencode($value);
2859
+						}
2860
+					}
2861
+					continue;
2862
+				}
2863
+				$args_to_merge[$query_param] = $query_value;
2864
+			}
2865
+			//now let's merge these arguments but override with what was specifically sent in to the
2866
+			//redirect.
2867
+			$query_args = array_merge($args_to_merge, $query_args);
2868
+		}
2869
+		$this->_process_notices($query_args);
2870
+		// generate redirect url
2871
+		// if redirecting to anything other than the main page, add a nonce
2872
+		if (isset($query_args['action'])) {
2873
+			// manually generate wp_nonce and merge that with the query vars becuz the wp_nonce_url function wrecks havoc on some vars
2874
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
2875
+		}
2876
+		//we're adding some hooks and filters in here for processing any things just before redirects (example: an admin page has done an insert or update and we want to run something after that).
2877
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
2878
+		$redirect_url = apply_filters('FHEE_redirect_' . $classname . $this->_req_action, self::add_query_args_and_nonce($query_args, $redirect_url), $query_args);
2879
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
2880
+		if (defined('DOING_AJAX')) {
2881
+			$default_data = array(
2882
+					'close'        => true,
2883
+					'redirect_url' => $redirect_url,
2884
+					'where'        => 'main',
2885
+					'what'         => 'append',
2886
+			);
2887
+			$this->_template_args['success'] = $success;
2888
+			$this->_template_args['data'] = ! empty($this->_template_args['data']) ? array_merge($default_data, $this->_template_args['data']) : $default_data;
2889
+			$this->_return_json();
2890
+		}
2891
+		wp_safe_redirect($redirect_url);
2892
+		exit();
2893
+	}
2894
+
2895
+
2896
+
2897
+	/**
2898
+	 * process any notices before redirecting (or returning ajax request)
2899
+	 * This method sets the $this->_template_args['notices'] attribute;
2900
+	 *
2901
+	 * @param  array $query_args        any query args that need to be used for notice transient ('action')
2902
+	 * @param bool   $skip_route_verify This is typically used when we are processing notices REALLY early and page_routes haven't been defined yet.
2903
+	 * @param bool   $sticky_notices    This is used to flag that regardless of whether this is doing_ajax or not, we still save a transient for the notice.
2904
+	 * @return void
2905
+	 */
2906
+	protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
2907
+	{
2908
+		//first let's set individual error properties if doing_ajax and the properties aren't already set.
2909
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2910
+			$notices = EE_Error::get_notices(false);
2911
+			if (empty($this->_template_args['success'])) {
2912
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
2913
+			}
2914
+			if (empty($this->_template_args['errors'])) {
2915
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
2916
+			}
2917
+			if (empty($this->_template_args['attention'])) {
2918
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
2919
+			}
2920
+		}
2921
+		$this->_template_args['notices'] = EE_Error::get_notices();
2922
+		//IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
2923
+		if ( ! defined('DOING_AJAX') || $sticky_notices) {
2924
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
2925
+			$this->_add_transient($route, $this->_template_args['notices'], true, $skip_route_verify);
2926
+		}
2927
+	}
2928
+
2929
+
2930
+
2931
+	/**
2932
+	 * get_action_link_or_button
2933
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
2934
+	 *
2935
+	 * @param string $action        use this to indicate which action the url is generated with.
2936
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key) property.
2937
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
2938
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
2939
+	 * @param string $base_url      If this is not provided
2940
+	 *                              the _admin_base_url will be used as the default for the button base_url.
2941
+	 *                              Otherwise this value will be used.
2942
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
2943
+	 * @return string
2944
+	 * @throws \EE_Error
2945
+	 */
2946
+	public function get_action_link_or_button(
2947
+			$action,
2948
+			$type = 'add',
2949
+			$extra_request = array(),
2950
+			$class = 'button-primary',
2951
+			$base_url = '',
2952
+			$exclude_nonce = false
2953
+	) {
2954
+		//first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
2955
+		if (empty($base_url) && ! isset($this->_page_routes[$action])) {
2956
+			throw new EE_Error(
2957
+					sprintf(
2958
+							__(
2959
+									'There is no page route for given action for the button.  This action was given: %s',
2960
+									'event_espresso'
2961
+							),
2962
+							$action
2963
+					)
2964
+			);
2965
+		}
2966
+		if ( ! isset($this->_labels['buttons'][$type])) {
2967
+			throw new EE_Error(
2968
+					sprintf(
2969
+							__(
2970
+									'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
2971
+									'event_espresso'
2972
+							),
2973
+							$type
2974
+					)
2975
+			);
2976
+		}
2977
+		//finally check user access for this button.
2978
+		$has_access = $this->check_user_access($action, true);
2979
+		if ( ! $has_access) {
2980
+			return '';
2981
+		}
2982
+		$_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
2983
+		$query_args = array(
2984
+				'action' => $action,
2985
+		);
2986
+		//merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
2987
+		if ( ! empty($extra_request)) {
2988
+			$query_args = array_merge($extra_request, $query_args);
2989
+		}
2990
+		$url = self::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
2991
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
2992
+	}
2993
+
2994
+
2995
+
2996
+	/**
2997
+	 * _per_page_screen_option
2998
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
2999
+	 *
3000
+	 * @return void
3001
+	 */
3002
+	protected function _per_page_screen_option()
3003
+	{
3004
+		$option = 'per_page';
3005
+		$args = array(
3006
+				'label'   => $this->_admin_page_title,
3007
+				'default' => 10,
3008
+				'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3009
+		);
3010
+		//ONLY add the screen option if the user has access to it.
3011
+		if ($this->check_user_access($this->_current_view, true)) {
3012
+			add_screen_option($option, $args);
3013
+		}
3014
+	}
3015
+
3016
+
3017
+
3018
+	/**
3019
+	 * set_per_page_screen_option
3020
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3021
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than admin_menu.
3022
+	 *
3023
+	 * @access private
3024
+	 * @return void
3025
+	 */
3026
+	private function _set_per_page_screen_options()
3027
+	{
3028
+		if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3029
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3030
+			if ( ! $user = wp_get_current_user()) {
3031
+				return;
3032
+			}
3033
+			$option = $_POST['wp_screen_options']['option'];
3034
+			$value = $_POST['wp_screen_options']['value'];
3035
+			if ($option != sanitize_key($option)) {
3036
+				return;
3037
+			}
3038
+			$map_option = $option;
3039
+			$option = str_replace('-', '_', $option);
3040
+			switch ($map_option) {
3041
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3042
+					$value = (int)$value;
3043
+					if ($value < 1 || $value > 999) {
3044
+						return;
3045
+					}
3046
+					break;
3047
+				default:
3048
+					$value = apply_filters('FHEE__EE_Admin_Page___set_per_page_screen_options__value', false, $option, $value);
3049
+					if (false === $value) {
3050
+						return;
3051
+					}
3052
+					break;
3053
+			}
3054
+			update_user_meta($user->ID, $option, $value);
3055
+			wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3056
+			exit;
3057
+		}
3058
+	}
3059
+
3060
+
3061
+
3062
+	/**
3063
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3064
+	 *
3065
+	 * @param array $data array that will be assigned to template args.
3066
+	 */
3067
+	public function set_template_args($data)
3068
+	{
3069
+		$this->_template_args = array_merge($this->_template_args, (array)$data);
3070
+	}
3071
+
3072
+
3073
+
3074
+	/**
3075
+	 * This makes available the WP transient system for temporarily moving data between routes
3076
+	 *
3077
+	 * @access protected
3078
+	 * @param string $route             the route that should receive the transient
3079
+	 * @param array  $data              the data that gets sent
3080
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a normal route transient.
3081
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used when we are adding a transient before page_routes have been defined.
3082
+	 * @return void
3083
+	 */
3084
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3085
+	{
3086
+		$user_id = get_current_user_id();
3087
+		if ( ! $skip_route_verify) {
3088
+			$this->_verify_route($route);
3089
+		}
3090
+		//now let's set the string for what kind of transient we're setting
3091
+		$transient = $notices ? 'ee_rte_n_tx_' . $route . '_' . $user_id : 'rte_tx_' . $route . '_' . $user_id;
3092
+		$data = $notices ? array('notices' => $data) : $data;
3093
+		//is there already a transient for this route?  If there is then let's ADD to that transient
3094
+		$existing = is_multisite() && is_network_admin() ? get_site_transient($transient) : get_transient($transient);
3095
+		if ($existing) {
3096
+			$data = array_merge((array)$data, (array)$existing);
3097
+		}
3098
+		if (is_multisite() && is_network_admin()) {
3099
+			set_site_transient($transient, $data, 8);
3100
+		} else {
3101
+			set_transient($transient, $data, 8);
3102
+		}
3103
+	}
3104
+
3105
+
3106
+
3107
+	/**
3108
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3109
+	 *
3110
+	 * @param bool $notices true we get notices transient. False we just return normal route transient
3111
+	 * @return mixed data
3112
+	 */
3113
+	protected function _get_transient($notices = false, $route = false)
3114
+	{
3115
+		$user_id = get_current_user_id();
3116
+		$route = ! $route ? $this->_req_action : $route;
3117
+		$transient = $notices ? 'ee_rte_n_tx_' . $route . '_' . $user_id : 'rte_tx_' . $route . '_' . $user_id;
3118
+		$data = is_multisite() && is_network_admin() ? get_site_transient($transient) : get_transient($transient);
3119
+		//delete transient after retrieval (just in case it hasn't expired);
3120
+		if (is_multisite() && is_network_admin()) {
3121
+			delete_site_transient($transient);
3122
+		} else {
3123
+			delete_transient($transient);
3124
+		}
3125
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3126
+	}
3127
+
3128
+
3129
+
3130
+	/**
3131
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but would not be called later.
3132
+	 * This will be assigned to run on a specific EE Admin page. (place the method in the default route callback on the EE_Admin page you want it run.)
3133
+	 *
3134
+	 * @return void
3135
+	 */
3136
+	protected function _transient_garbage_collection()
3137
+	{
3138
+		global $wpdb;
3139
+		//retrieve all existing transients
3140
+		$query = "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3141
+		if ($results = $wpdb->get_results($query)) {
3142
+			foreach ($results as $result) {
3143
+				$transient = str_replace('_transient_', '', $result->option_name);
3144
+				get_transient($transient);
3145
+				if (is_multisite() && is_network_admin()) {
3146
+					get_site_transient($transient);
3147
+				}
3148
+			}
3149
+		}
3150
+	}
3151
+
3152
+
3153
+
3154
+	/**
3155
+	 * get_view
3156
+	 *
3157
+	 * @access public
3158
+	 * @return string content of _view property
3159
+	 */
3160
+	public function get_view()
3161
+	{
3162
+		return $this->_view;
3163
+	}
3164
+
3165
+
3166
+
3167
+	/**
3168
+	 * getter for the protected $_views property
3169
+	 *
3170
+	 * @return array
3171
+	 */
3172
+	public function get_views()
3173
+	{
3174
+		return $this->_views;
3175
+	}
3176
+
3177
+
3178
+
3179
+	/**
3180
+	 * get_current_page
3181
+	 *
3182
+	 * @access public
3183
+	 * @return string _current_page property value
3184
+	 */
3185
+	public function get_current_page()
3186
+	{
3187
+		return $this->_current_page;
3188
+	}
3189
+
3190
+
3191
+
3192
+	/**
3193
+	 * get_current_view
3194
+	 *
3195
+	 * @access public
3196
+	 * @return string _current_view property value
3197
+	 */
3198
+	public function get_current_view()
3199
+	{
3200
+		return $this->_current_view;
3201
+	}
3202
+
3203
+
3204
+
3205
+	/**
3206
+	 * get_current_screen
3207
+	 *
3208
+	 * @access public
3209
+	 * @return object The current WP_Screen object
3210
+	 */
3211
+	public function get_current_screen()
3212
+	{
3213
+		return $this->_current_screen;
3214
+	}
3215
+
3216
+
3217
+
3218
+	/**
3219
+	 * get_current_page_view_url
3220
+	 *
3221
+	 * @access public
3222
+	 * @return string This returns the url for the current_page_view.
3223
+	 */
3224
+	public function get_current_page_view_url()
3225
+	{
3226
+		return $this->_current_page_view_url;
3227
+	}
3228
+
3229
+
3230
+
3231
+	/**
3232
+	 * just returns the _req_data property
3233
+	 *
3234
+	 * @return array
3235
+	 */
3236
+	public function get_request_data()
3237
+	{
3238
+		return $this->_req_data;
3239
+	}
3240
+
3241
+
3242
+
3243
+	/**
3244
+	 * returns the _req_data protected property
3245
+	 *
3246
+	 * @return string
3247
+	 */
3248
+	public function get_req_action()
3249
+	{
3250
+		return $this->_req_action;
3251
+	}
3252
+
3253
+
3254
+
3255
+	/**
3256
+	 * @return bool  value of $_is_caf property
3257
+	 */
3258
+	public function is_caf()
3259
+	{
3260
+		return $this->_is_caf;
3261
+	}
3262
+
3263
+
3264
+
3265
+	/**
3266
+	 * @return mixed
3267
+	 */
3268
+	public function default_espresso_metaboxes()
3269
+	{
3270
+		return $this->_default_espresso_metaboxes;
3271
+	}
3272
+
3273
+
3274
+
3275
+	/**
3276
+	 * @return mixed
3277
+	 */
3278
+	public function admin_base_url()
3279
+	{
3280
+		return $this->_admin_base_url;
3281
+	}
3282
+
3283
+
3284
+
3285
+	/**
3286
+	 * @return mixed
3287
+	 */
3288
+	public function wp_page_slug()
3289
+	{
3290
+		return $this->_wp_page_slug;
3291
+	}
3292
+
3293
+
3294
+
3295
+	/**
3296
+	 * updates  espresso configuration settings
3297
+	 *
3298
+	 * @access    protected
3299
+	 * @param string                   $tab
3300
+	 * @param EE_Config_Base|EE_Config $config
3301
+	 * @param string                   $file file where error occurred
3302
+	 * @param string                   $func function  where error occurred
3303
+	 * @param string                   $line line no where error occurred
3304
+	 * @return boolean
3305
+	 */
3306
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
3307
+	{
3308
+		//remove any options that are NOT going to be saved with the config settings.
3309
+		if (isset($config->core->ee_ueip_optin)) {
3310
+			$config->core->ee_ueip_has_notified = true;
3311
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
3312
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
3313
+			update_option('ee_ueip_has_notified', true);
3314
+		}
3315
+		// and save it (note we're also doing the network save here)
3316
+		$net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
3317
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
3318
+		if ($config_saved && $net_saved) {
3319
+			EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
3320
+			return true;
3321
+		} else {
3322
+			EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
3323
+			return false;
3324
+		}
3325
+	}
3326
+
3327
+
3328
+
3329
+	/**
3330
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
3331
+	 *
3332
+	 * @return array
3333
+	 */
3334
+	public function get_yes_no_values()
3335
+	{
3336
+		return $this->_yes_no_values;
3337
+	}
3338
+
3339
+
3340
+
3341
+	protected function _get_dir()
3342
+	{
3343
+		$reflector = new ReflectionClass(get_class($this));
3344
+		return dirname($reflector->getFileName());
3345
+	}
3346
+
3347
+
3348
+
3349
+	/**
3350
+	 * A helper for getting a "next link".
3351
+	 *
3352
+	 * @param string $url   The url to link to
3353
+	 * @param string $class The class to use.
3354
+	 * @return string
3355
+	 */
3356
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
3357
+	{
3358
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
3359
+	}
3360
+
3361
+
3362
+
3363
+	/**
3364
+	 * A helper for getting a "previous link".
3365
+	 *
3366
+	 * @param string $url   The url to link to
3367
+	 * @param string $class The class to use.
3368
+	 * @return string
3369
+	 */
3370
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
3371
+	{
3372
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
3373
+	}
3374
+
3375
+
3376
+
3377
+
3378
+
3379
+
3380
+
3381
+	//below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
3382
+	/**
3383
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller knows that the _REG_ID isn't in the req_data array but CAN obtain it, the caller should ADD the _REG_ID to the _req_data
3384
+	 * array.
3385
+	 *
3386
+	 * @return bool success/fail
3387
+	 */
3388
+	protected function _process_resend_registration()
3389
+	{
3390
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
3391
+		do_action('AHEE__EE_Admin_Page___process_resend_registration', $this->_template_args['success'], $this->_req_data);
3392
+		return $this->_template_args['success'];
3393
+	}
3394
+
3395
+
3396
+
3397
+	/**
3398
+	 * This automatically processes any payment message notifications when manual payment has been applied.
3399
+	 *
3400
+	 * @access protected
3401
+	 * @param \EE_Payment $payment
3402
+	 * @return bool success/fail
3403
+	 */
3404
+	protected function _process_payment_notification(EE_Payment $payment)
3405
+	{
3406
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
3407
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
3408
+		$this->_template_args['success'] = apply_filters('FHEE__EE_Admin_Page___process_admin_payment_notification__success', false, $payment);
3409
+		return $this->_template_args['success'];
3410
+	}
3411 3411
 
3412 3412
 
3413 3413
 }
Please login to merge, or discard this patch.
core/EE_System.core.php 2 patches
Indentation   +1406 added lines, -1406 removed lines patch added patch discarded remove patch
@@ -6,7 +6,7 @@  discard block
 block discarded – undo
6 6
 
7 7
 
8 8
 if ( ! defined('EVENT_ESPRESSO_VERSION')) {
9
-    exit('No direct script access allowed');
9
+	exit('No direct script access allowed');
10 10
 }
11 11
 
12 12
 
@@ -23,1411 +23,1411 @@  discard block
 block discarded – undo
23 23
 {
24 24
 
25 25
 
26
-    /**
27
-     * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
28
-     * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
29
-     */
30
-    const req_type_normal = 0;
31
-
32
-    /**
33
-     * Indicates this is a brand new installation of EE so we should install
34
-     * tables and default data etc
35
-     */
36
-    const req_type_new_activation = 1;
37
-
38
-    /**
39
-     * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
40
-     * and we just exited maintenance mode). We MUST check the database is setup properly
41
-     * and that default data is setup too
42
-     */
43
-    const req_type_reactivation = 2;
44
-
45
-    /**
46
-     * indicates that EE has been upgraded since its previous request.
47
-     * We may have data migration scripts to call and will want to trigger maintenance mode
48
-     */
49
-    const req_type_upgrade = 3;
50
-
51
-    /**
52
-     * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
53
-     */
54
-    const req_type_downgrade = 4;
55
-
56
-    /**
57
-     * @deprecated since version 4.6.0.dev.006
58
-     * Now whenever a new_activation is detected the request type is still just
59
-     * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
60
-     * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
61
-     * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
62
-     * (Specifically, when the migration manager indicates migrations are finished
63
-     * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
64
-     */
65
-    const req_type_activation_but_not_installed = 5;
66
-
67
-    /**
68
-     * option prefix for recording the activation history (like core's "espresso_db_update") of addons
69
-     */
70
-    const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
71
-
72
-
73
-    /**
74
-     * @var EE_System $_instance
75
-     */
76
-    private static $_instance;
77
-
78
-    /**
79
-     * @var EE_Registry $registry
80
-     */
81
-    protected $registry;
82
-
83
-    /**
84
-     * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
85
-     * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
86
-     *
87
-     * @var int $_req_type
88
-     */
89
-    private $_req_type;
90
-
91
-    /**
92
-     * Whether or not there was a non-micro version change in EE core version during this request
93
-     *
94
-     * @var boolean $_major_version_change
95
-     */
96
-    private $_major_version_change = false;
97
-
98
-
99
-
100
-    /**
101
-     * @singleton method used to instantiate class object
102
-     * @access    public
103
-     * @param  EE_Registry $Registry
104
-     * @return EE_System
105
-     */
106
-    public static function instance(EE_Registry $Registry = null)
107
-    {
108
-        // check if class object is instantiated
109
-        if ( ! self::$_instance instanceof EE_System) {
110
-            self::$_instance = new self($Registry);
111
-        }
112
-        return self::$_instance;
113
-    }
114
-
115
-
116
-
117
-    /**
118
-     * resets the instance and returns it
119
-     *
120
-     * @return EE_System
121
-     */
122
-    public static function reset()
123
-    {
124
-        self::$_instance->_req_type = null;
125
-        //make sure none of the old hooks are left hanging around
126
-        remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
127
-        //we need to reset the migration manager in order for it to detect DMSs properly
128
-        EE_Data_Migration_Manager::reset();
129
-        self::instance()->detect_activations_or_upgrades();
130
-        self::instance()->perform_activations_upgrades_and_migrations();
131
-        return self::instance();
132
-    }
133
-
134
-
135
-
136
-    /**
137
-     *    sets hooks for running rest of system
138
-     *    provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
139
-     *    starting EE Addons from any other point may lead to problems
140
-     *
141
-     * @access private
142
-     * @param  EE_Registry $Registry
143
-     */
144
-    private function __construct(EE_Registry $Registry)
145
-    {
146
-        $this->registry = $Registry;
147
-        do_action('AHEE__EE_System__construct__begin', $this);
148
-        // allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
149
-        add_action('AHEE__EE_Bootstrap__load_espresso_addons', array($this, 'load_espresso_addons'));
150
-        // when an ee addon is activated, we want to call the core hook(s) again
151
-        // because the newly-activated addon didn't get a chance to run at all
152
-        add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
153
-        // detect whether install or upgrade
154
-        add_action('AHEE__EE_Bootstrap__detect_activations_or_upgrades', array($this, 'detect_activations_or_upgrades'),
155
-            3);
156
-        // load EE_Config, EE_Textdomain, etc
157
-        add_action('AHEE__EE_Bootstrap__load_core_configuration', array($this, 'load_core_configuration'), 5);
158
-        // load EE_Config, EE_Textdomain, etc
159
-        add_action('AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
160
-            array($this, 'register_shortcodes_modules_and_widgets'), 7);
161
-        // you wanna get going? I wanna get going... let's get going!
162
-        add_action('AHEE__EE_Bootstrap__brew_espresso', array($this, 'brew_espresso'), 9);
163
-        //other housekeeping
164
-        //exclude EE critical pages from wp_list_pages
165
-        add_filter('wp_list_pages_excludes', array($this, 'remove_pages_from_wp_list_pages'), 10);
166
-        // ALL EE Addons should use the following hook point to attach their initial setup too
167
-        // it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
168
-        do_action('AHEE__EE_System__construct__complete', $this);
169
-    }
170
-
171
-
172
-
173
-    /**
174
-     * load_espresso_addons
175
-     * allow addons to load first so that they can set hooks for running DMS's, etc
176
-     * this is hooked into both:
177
-     *    'AHEE__EE_Bootstrap__load_core_configuration'
178
-     *        which runs during the WP 'plugins_loaded' action at priority 5
179
-     *    and the WP 'activate_plugin' hook point
180
-     *
181
-     * @access public
182
-     * @return void
183
-     * @throws EE_Error
184
-     */
185
-    public function load_espresso_addons()
186
-    {
187
-        // set autoloaders for all of the classes implementing EEI_Plugin_API
188
-        // which provide helpers for EE plugin authors to more easily register certain components with EE.
189
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
190
-        //load and setup EE_Capabilities
191
-        $this->registry->load_core('Capabilities');
192
-        //caps need to be initialized on every request so that capability maps are set.
193
-        //@see https://events.codebasehq.com/projects/event-espresso/tickets/8674
194
-        $this->registry->CAP->init_caps();
195
-        do_action('AHEE__EE_System__load_espresso_addons');
196
-        //if the WP API basic auth plugin isn't already loaded, load it now.
197
-        //We want it for mobile apps. Just include the entire plugin
198
-        //also, don't load the basic auth when a plugin is getting activated, because
199
-        //it could be the basic auth plugin, and it doesn't check if its methods are already defined
200
-        //and causes a fatal error
201
-        if (
202
-            ! (isset($_GET['activate']) && $_GET['activate'] === 'true')
203
-            && ! function_exists('json_basic_auth_handler')
204
-            && ! function_exists('json_basic_auth_error')
205
-            && ! (
206
-                isset($_GET['action'])
207
-                && in_array($_GET['action'], array('activate', 'activate-selected'), true)
208
-            )
209
-        ) {
210
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
211
-        }
212
-        do_action('AHEE__EE_System__load_espresso_addons__complete');
213
-    }
214
-
215
-
216
-
217
-    /**
218
-     * detect_activations_or_upgrades
219
-     * Checks for activation or upgrade of core first;
220
-     * then also checks if any registered addons have been activated or upgraded
221
-     * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
222
-     * which runs during the WP 'plugins_loaded' action at priority 3
223
-     *
224
-     * @access public
225
-     * @return void
226
-     */
227
-    public function detect_activations_or_upgrades()
228
-    {
229
-        //first off: let's make sure to handle core
230
-        $this->detect_if_activation_or_upgrade();
231
-        foreach ($this->registry->addons as $addon) {
232
-            //detect teh request type for that addon
233
-            $addon->detect_activation_or_upgrade();
234
-        }
235
-    }
236
-
237
-
238
-
239
-    /**
240
-     * detect_if_activation_or_upgrade
241
-     * Takes care of detecting whether this is a brand new install or code upgrade,
242
-     * and either setting up the DB or setting up maintenance mode etc.
243
-     *
244
-     * @access public
245
-     * @return void
246
-     */
247
-    public function detect_if_activation_or_upgrade()
248
-    {
249
-        do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
250
-        // load M-Mode class
251
-        $this->registry->load_core('Maintenance_Mode');
252
-        // check if db has been updated, or if its a brand-new installation
253
-        $espresso_db_update = $this->fix_espresso_db_upgrade_option();
254
-        $request_type = $this->detect_req_type($espresso_db_update);
255
-        //EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
256
-        switch ($request_type) {
257
-            case EE_System::req_type_new_activation:
258
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
259
-                $this->_handle_core_version_change($espresso_db_update);
260
-                break;
261
-            case EE_System::req_type_reactivation:
262
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
263
-                $this->_handle_core_version_change($espresso_db_update);
264
-                break;
265
-            case EE_System::req_type_upgrade:
266
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
267
-                //migrations may be required now that we've upgraded
268
-                EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
269
-                $this->_handle_core_version_change($espresso_db_update);
270
-                //				echo "done upgrade";die;
271
-                break;
272
-            case EE_System::req_type_downgrade:
273
-                do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
274
-                //its possible migrations are no longer required
275
-                EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
276
-                $this->_handle_core_version_change($espresso_db_update);
277
-                break;
278
-            case EE_System::req_type_normal:
279
-            default:
280
-                //				$this->_maybe_redirect_to_ee_about();
281
-                break;
282
-        }
283
-        do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
284
-    }
285
-
286
-
287
-
288
-    /**
289
-     * Updates the list of installed versions and sets hooks for
290
-     * initializing the database later during the request
291
-     *
292
-     * @param array $espresso_db_update
293
-     */
294
-    protected function _handle_core_version_change($espresso_db_update)
295
-    {
296
-        $this->update_list_of_installed_versions($espresso_db_update);
297
-        //get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
298
-        add_action('AHEE__EE_System__perform_activations_upgrades_and_migrations',
299
-            array($this, 'initialize_db_if_no_migrations_required'));
300
-    }
301
-
302
-
303
-
304
-    /**
305
-     * standardizes the wp option 'espresso_db_upgrade' which actually stores
306
-     * information about what versions of EE have been installed and activated,
307
-     * NOT necessarily the state of the database
308
-     *
309
-     * @param mixed $espresso_db_update the value of the WordPress option.
310
-     *                                            If not supplied, fetches it from the options table
311
-     * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
312
-     */
313
-    private function fix_espresso_db_upgrade_option($espresso_db_update = null)
314
-    {
315
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
316
-        if ( ! $espresso_db_update) {
317
-            $espresso_db_update = get_option('espresso_db_update');
318
-        }
319
-        // check that option is an array
320
-        if ( ! is_array($espresso_db_update)) {
321
-            // if option is FALSE, then it never existed
322
-            if ($espresso_db_update === false) {
323
-                // make $espresso_db_update an array and save option with autoload OFF
324
-                $espresso_db_update = array();
325
-                add_option('espresso_db_update', $espresso_db_update, '', 'no');
326
-            } else {
327
-                // option is NOT FALSE but also is NOT an array, so make it an array and save it
328
-                $espresso_db_update = array($espresso_db_update => array());
329
-                update_option('espresso_db_update', $espresso_db_update);
330
-            }
331
-        } else {
332
-            $corrected_db_update = array();
333
-            //if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
334
-            foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
335
-                if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
336
-                    //the key is an int, and the value IS NOT an array
337
-                    //so it must be numerically-indexed, where values are versions installed...
338
-                    //fix it!
339
-                    $version_string = $should_be_array;
340
-                    $corrected_db_update[$version_string] = array('unknown-date');
341
-                } else {
342
-                    //ok it checks out
343
-                    $corrected_db_update[$should_be_version_string] = $should_be_array;
344
-                }
345
-            }
346
-            $espresso_db_update = $corrected_db_update;
347
-            update_option('espresso_db_update', $espresso_db_update);
348
-        }
349
-        do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
350
-        return $espresso_db_update;
351
-    }
352
-
353
-
354
-
355
-    /**
356
-     * Does the traditional work of setting up the plugin's database and adding default data.
357
-     * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
358
-     * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
359
-     * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
360
-     * so that it will be done when migrations are finished
361
-     *
362
-     * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
363
-     * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
364
-     *                                       This is a resource-intensive job
365
-     *                                       so we prefer to only do it when necessary
366
-     * @return void
367
-     * @throws EE_Error
368
-     */
369
-    public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
370
-    {
371
-        $request_type = $this->detect_req_type();
372
-        //only initialize system if we're not in maintenance mode.
373
-        if (EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
374
-            update_option('ee_flush_rewrite_rules', true);
375
-            if ($verify_schema) {
376
-                EEH_Activation::initialize_db_and_folders();
377
-            }
378
-            EEH_Activation::initialize_db_content();
379
-            EEH_Activation::system_initialization();
380
-            if ($initialize_addons_too) {
381
-                $this->initialize_addons();
382
-            }
383
-        } else {
384
-            EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
385
-        }
386
-        if ($request_type === EE_System::req_type_new_activation
387
-            || $request_type === EE_System::req_type_reactivation
388
-            || (
389
-                $request_type === EE_System::req_type_upgrade
390
-                && $this->is_major_version_change()
391
-            )
392
-        ) {
393
-            add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
394
-        }
395
-    }
396
-
397
-
398
-
399
-    /**
400
-     * Initializes the db for all registered addons
401
-     *
402
-     * @throws EE_Error
403
-     */
404
-    public function initialize_addons()
405
-    {
406
-        //foreach registered addon, make sure its db is up-to-date too
407
-        foreach ($this->registry->addons as $addon) {
408
-            $addon->initialize_db_if_no_migrations_required();
409
-        }
410
-    }
411
-
412
-
413
-
414
-    /**
415
-     * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
416
-     *
417
-     * @param    array  $version_history
418
-     * @param    string $current_version_to_add version to be added to the version history
419
-     * @return    boolean success as to whether or not this option was changed
420
-     */
421
-    public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
422
-    {
423
-        if ( ! $version_history) {
424
-            $version_history = $this->fix_espresso_db_upgrade_option($version_history);
425
-        }
426
-        if ($current_version_to_add === null) {
427
-            $current_version_to_add = espresso_version();
428
-        }
429
-        $version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time());
430
-        // re-save
431
-        return update_option('espresso_db_update', $version_history);
432
-    }
433
-
434
-
435
-
436
-    /**
437
-     * Detects if the current version indicated in the has existed in the list of
438
-     * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
439
-     *
440
-     * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
441
-     *                                  If not supplied, fetches it from the options table.
442
-     *                                  Also, caches its result so later parts of the code can also know whether
443
-     *                                  there's been an update or not. This way we can add the current version to
444
-     *                                  espresso_db_update, but still know if this is a new install or not
445
-     * @return int one of the constants on EE_System::req_type_
446
-     */
447
-    public function detect_req_type($espresso_db_update = null)
448
-    {
449
-        if ($this->_req_type === null) {
450
-            $espresso_db_update = ! empty($espresso_db_update) ? $espresso_db_update
451
-                : $this->fix_espresso_db_upgrade_option();
452
-            $this->_req_type = EE_System::detect_req_type_given_activation_history($espresso_db_update,
453
-                'ee_espresso_activation', espresso_version());
454
-            $this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
455
-        }
456
-        return $this->_req_type;
457
-    }
458
-
459
-
460
-
461
-    /**
462
-     * Returns whether or not there was a non-micro version change (ie, change in either
463
-     * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
464
-     * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
465
-     *
466
-     * @param $activation_history
467
-     * @return bool
468
-     */
469
-    protected function _detect_major_version_change($activation_history)
470
-    {
471
-        $previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
472
-        $previous_version_parts = explode('.', $previous_version);
473
-        $current_version_parts = explode('.', espresso_version());
474
-        return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
475
-               && ($previous_version_parts[0] !== $current_version_parts[0]
476
-                   || $previous_version_parts[1] !== $current_version_parts[1]
477
-               );
478
-    }
479
-
480
-
481
-
482
-    /**
483
-     * Returns true if either the major or minor version of EE changed during this request.
484
-     * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
485
-     *
486
-     * @return bool
487
-     */
488
-    public function is_major_version_change()
489
-    {
490
-        return $this->_major_version_change;
491
-    }
492
-
493
-
494
-
495
-    /**
496
-     * Determines the request type for any ee addon, given three piece of info: the current array of activation
497
-     * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
498
-     * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
499
-     * just activated to (for core that will always be espresso_version())
500
-     *
501
-     * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
502
-     *                                                 ee plugin. for core that's 'espresso_db_update'
503
-     * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
504
-     *                                                 indicate that this plugin was just activated
505
-     * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
506
-     *                                                 espresso_version())
507
-     * @return int one of the constants on EE_System::req_type_*
508
-     */
509
-    public static function detect_req_type_given_activation_history(
510
-        $activation_history_for_addon,
511
-        $activation_indicator_option_name,
512
-        $version_to_upgrade_to
513
-    ) {
514
-        $version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
515
-        if ($activation_history_for_addon) {
516
-            //it exists, so this isn't a completely new install
517
-            //check if this version already in that list of previously installed versions
518
-            if ( ! isset($activation_history_for_addon[$version_to_upgrade_to])) {
519
-                //it a version we haven't seen before
520
-                if ($version_is_higher === 1) {
521
-                    $req_type = EE_System::req_type_upgrade;
522
-                } else {
523
-                    $req_type = EE_System::req_type_downgrade;
524
-                }
525
-                delete_option($activation_indicator_option_name);
526
-            } else {
527
-                // its not an update. maybe a reactivation?
528
-                if (get_option($activation_indicator_option_name, false)) {
529
-                    if ($version_is_higher === -1) {
530
-                        $req_type = EE_System::req_type_downgrade;
531
-                    } elseif ($version_is_higher === 0) {
532
-                        //we've seen this version before, but it's an activation. must be a reactivation
533
-                        $req_type = EE_System::req_type_reactivation;
534
-                    } else {//$version_is_higher === 1
535
-                        $req_type = EE_System::req_type_upgrade;
536
-                    }
537
-                    delete_option($activation_indicator_option_name);
538
-                } else {
539
-                    //we've seen this version before and the activation indicate doesn't show it was just activated
540
-                    if ($version_is_higher === -1) {
541
-                        $req_type = EE_System::req_type_downgrade;
542
-                    } elseif ($version_is_higher === 0) {
543
-                        //we've seen this version before and it's not an activation. its normal request
544
-                        $req_type = EE_System::req_type_normal;
545
-                    } else {//$version_is_higher === 1
546
-                        $req_type = EE_System::req_type_upgrade;
547
-                    }
548
-                }
549
-            }
550
-        } else {
551
-            //brand new install
552
-            $req_type = EE_System::req_type_new_activation;
553
-            delete_option($activation_indicator_option_name);
554
-        }
555
-        return $req_type;
556
-    }
557
-
558
-
559
-
560
-    /**
561
-     * Detects if the $version_to_upgrade_to is higher than the most recent version in
562
-     * the $activation_history_for_addon
563
-     *
564
-     * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
565
-     *                                             sometimes containing 'unknown-date'
566
-     * @param string $version_to_upgrade_to        (current version)
567
-     * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
568
-     *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
569
-     *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
570
-     *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
571
-     */
572
-    protected static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
573
-    {
574
-        //find the most recently-activated version
575
-        $most_recently_active_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
576
-        return version_compare($version_to_upgrade_to, $most_recently_active_version);
577
-    }
578
-
579
-
580
-
581
-    /**
582
-     * Gets the most recently active version listed in the activation history,
583
-     * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
584
-     *
585
-     * @param array $activation_history  (keys are versions, values are arrays of times activated,
586
-     *                                   sometimes containing 'unknown-date'
587
-     * @return string
588
-     */
589
-    protected static function _get_most_recently_active_version_from_activation_history($activation_history)
590
-    {
591
-        $most_recently_active_version_activation = '1970-01-01 00:00:00';
592
-        $most_recently_active_version = '0.0.0.dev.000';
593
-        if (is_array($activation_history)) {
594
-            foreach ($activation_history as $version => $times_activated) {
595
-                //check there is a record of when this version was activated. Otherwise,
596
-                //mark it as unknown
597
-                if ( ! $times_activated) {
598
-                    $times_activated = array('unknown-date');
599
-                }
600
-                if (is_string($times_activated)) {
601
-                    $times_activated = array($times_activated);
602
-                }
603
-                foreach ($times_activated as $an_activation) {
604
-                    if ($an_activation !== 'unknown-date' && $an_activation > $most_recently_active_version_activation) {
605
-                        $most_recently_active_version = $version;
606
-                        $most_recently_active_version_activation = $an_activation === 'unknown-date'
607
-                            ? '1970-01-01 00:00:00' : $an_activation;
608
-                    }
609
-                }
610
-            }
611
-        }
612
-        return $most_recently_active_version;
613
-    }
614
-
615
-
616
-
617
-    /**
618
-     * This redirects to the about EE page after activation
619
-     *
620
-     * @return void
621
-     */
622
-    public function redirect_to_about_ee()
623
-    {
624
-        $notices = EE_Error::get_notices(false);
625
-        //if current user is an admin and it's not an ajax or rest request
626
-        if (
627
-            ! (defined('DOING_AJAX') && DOING_AJAX)
628
-            && ! (defined('REST_REQUEST') && REST_REQUEST)
629
-            && ! isset($notices['errors'])
630
-            && apply_filters(
631
-                'FHEE__EE_System__redirect_to_about_ee__do_redirect',
632
-                $this->registry->CAP->current_user_can('manage_options', 'espresso_about_default')
633
-            )
634
-        ) {
635
-            $query_params = array('page' => 'espresso_about');
636
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
637
-                $query_params['new_activation'] = true;
638
-            }
639
-            if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
640
-                $query_params['reactivation'] = true;
641
-            }
642
-            $url = add_query_arg($query_params, admin_url('admin.php'));
643
-            wp_safe_redirect($url);
644
-            exit();
645
-        }
646
-    }
647
-
648
-
649
-
650
-    /**
651
-     * load_core_configuration
652
-     * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
653
-     * which runs during the WP 'plugins_loaded' action at priority 5
654
-     *
655
-     * @return void
656
-     * @throws \ReflectionException
657
-     */
658
-    public function load_core_configuration()
659
-    {
660
-        do_action('AHEE__EE_System__load_core_configuration__begin', $this);
661
-        $this->registry->load_core('EE_Load_Textdomain');
662
-        //load textdomain
663
-        EE_Load_Textdomain::load_textdomain();
664
-        // load and setup EE_Config and EE_Network_Config
665
-        $this->registry->load_core('Config');
666
-        $this->registry->load_core('Network_Config');
667
-        // setup autoloaders
668
-        // enable logging?
669
-        if ($this->registry->CFG->admin->use_full_logging) {
670
-            $this->registry->load_core('Log');
671
-        }
672
-        // check for activation errors
673
-        $activation_errors = get_option('ee_plugin_activation_errors', false);
674
-        if ($activation_errors) {
675
-            EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
676
-            update_option('ee_plugin_activation_errors', false);
677
-        }
678
-        // get model names
679
-        $this->_parse_model_names();
680
-        //load caf stuff a chance to play during the activation process too.
681
-        $this->_maybe_brew_regular();
682
-        do_action('AHEE__EE_System__load_core_configuration__complete', $this);
683
-    }
684
-
685
-
686
-
687
-    /**
688
-     * cycles through all of the models/*.model.php files, and assembles an array of model names
689
-     *
690
-     * @return void
691
-     * @throws ReflectionException
692
-     */
693
-    private function _parse_model_names()
694
-    {
695
-        //get all the files in the EE_MODELS folder that end in .model.php
696
-        $models = glob(EE_MODELS . '*.model.php');
697
-        $model_names = array();
698
-        $non_abstract_db_models = array();
699
-        foreach ($models as $model) {
700
-            // get model classname
701
-            $classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
702
-            $short_name = str_replace('EEM_', '', $classname);
703
-            $reflectionClass = new ReflectionClass($classname);
704
-            if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
705
-                $non_abstract_db_models[$short_name] = $classname;
706
-            }
707
-            $model_names[$short_name] = $classname;
708
-        }
709
-        $this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
710
-        $this->registry->non_abstract_db_models = apply_filters('FHEE__EE_System__parse_implemented_model_names',
711
-            $non_abstract_db_models);
712
-    }
713
-
714
-
715
-
716
-    /**
717
-     * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
718
-     * that need to be setup before our EE_System launches.
719
-     *
720
-     * @return void
721
-     */
722
-    private function _maybe_brew_regular()
723
-    {
724
-        if (( ! defined('EE_DECAF') || EE_DECAF !== true) && is_readable(EE_CAFF_PATH . 'brewing_regular.php')) {
725
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
726
-        }
727
-    }
728
-
729
-
730
-
731
-    /**
732
-     * register_shortcodes_modules_and_widgets
733
-     * generate lists of shortcodes and modules, then verify paths and classes
734
-     * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
735
-     * which runs during the WP 'plugins_loaded' action at priority 7
736
-     *
737
-     * @access public
738
-     * @return void
739
-     */
740
-    public function register_shortcodes_modules_and_widgets()
741
-    {
742
-        try {
743
-            // load, register, and add shortcodes the new way
744
-            new ShortcodesManager(
745
-            // and the old way, but we'll put it under control of the new system
746
-                EE_Config::getLegacyShortcodesManager()
747
-            );
748
-        } catch (Exception $exception) {
749
-            new ExceptionStackTraceDisplay($exception);
750
-        }
751
-        do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
752
-        // check for addons using old hook point
753
-        if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
754
-            $this->_incompatible_addon_error();
755
-        }
756
-    }
757
-
758
-
759
-
760
-    /**
761
-     * _incompatible_addon_error
762
-     *
763
-     * @access public
764
-     * @return void
765
-     */
766
-    private function _incompatible_addon_error()
767
-    {
768
-        // get array of classes hooking into here
769
-        $class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook('AHEE__EE_System__register_shortcodes_modules_and_addons');
770
-        if ( ! empty($class_names)) {
771
-            $msg = __('The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
772
-                'event_espresso');
773
-            $msg .= '<ul>';
774
-            foreach ($class_names as $class_name) {
775
-                $msg .= '<li><b>Event Espresso - ' . str_replace(array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
776
-                        $class_name) . '</b></li>';
777
-            }
778
-            $msg .= '</ul>';
779
-            $msg .= __('Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
780
-                'event_espresso');
781
-            // save list of incompatible addons to wp-options for later use
782
-            add_option('ee_incompatible_addons', $class_names, '', 'no');
783
-            if (is_admin()) {
784
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
785
-            }
786
-        }
787
-    }
788
-
789
-
790
-
791
-    /**
792
-     * brew_espresso
793
-     * begins the process of setting hooks for initializing EE in the correct order
794
-     * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
795
-     * which runs during the WP 'plugins_loaded' action at priority 9
796
-     *
797
-     * @return void
798
-     */
799
-    public function brew_espresso()
800
-    {
801
-        do_action('AHEE__EE_System__brew_espresso__begin', $this);
802
-        // load some final core systems
803
-        add_action('init', array($this, 'set_hooks_for_core'), 1);
804
-        add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
805
-        add_action('init', array($this, 'load_CPTs_and_session'), 5);
806
-        add_action('init', array($this, 'load_controllers'), 7);
807
-        add_action('init', array($this, 'core_loaded_and_ready'), 9);
808
-        add_action('init', array($this, 'initialize'), 10);
809
-        add_action('init', array($this, 'initialize_last'), 100);
810
-        add_action('admin_bar_menu', array($this, 'espresso_toolbar_items'), 100);
811
-        if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
812
-            // pew pew pew
813
-            $this->registry->load_core('PUE');
814
-            do_action('AHEE__EE_System__brew_espresso__after_pue_init');
815
-        }
816
-        do_action('AHEE__EE_System__brew_espresso__complete', $this);
817
-    }
818
-
819
-
820
-
821
-    /**
822
-     *    set_hooks_for_core
823
-     *
824
-     * @access public
825
-     * @return    void
826
-     */
827
-    public function set_hooks_for_core()
828
-    {
829
-        $this->_deactivate_incompatible_addons();
830
-        do_action('AHEE__EE_System__set_hooks_for_core');
831
-    }
832
-
833
-
834
-
835
-    /**
836
-     * Using the information gathered in EE_System::_incompatible_addon_error,
837
-     * deactivates any addons considered incompatible with the current version of EE
838
-     */
839
-    private function _deactivate_incompatible_addons()
840
-    {
841
-        $incompatible_addons = get_option('ee_incompatible_addons', array());
842
-        if ( ! empty($incompatible_addons)) {
843
-            $active_plugins = get_option('active_plugins', array());
844
-            foreach ($active_plugins as $active_plugin) {
845
-                foreach ($incompatible_addons as $incompatible_addon) {
846
-                    if (strpos($active_plugin, $incompatible_addon) !== false) {
847
-                        unset($_GET['activate']);
848
-                        espresso_deactivate_plugin($active_plugin);
849
-                    }
850
-                }
851
-            }
852
-        }
853
-    }
854
-
855
-
856
-
857
-    /**
858
-     *    perform_activations_upgrades_and_migrations
859
-     *
860
-     * @access public
861
-     * @return    void
862
-     */
863
-    public function perform_activations_upgrades_and_migrations()
864
-    {
865
-        //first check if we had previously attempted to setup EE's directories but failed
866
-        if (EEH_Activation::upload_directories_incomplete()) {
867
-            EEH_Activation::create_upload_directories();
868
-        }
869
-        do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
870
-    }
871
-
872
-
873
-
874
-    /**
875
-     *    load_CPTs_and_session
876
-     *
877
-     * @access public
878
-     * @return    void
879
-     */
880
-    public function load_CPTs_and_session()
881
-    {
882
-        do_action('AHEE__EE_System__load_CPTs_and_session__start');
883
-        // register Custom Post Types
884
-        $this->registry->load_core('Register_CPTs');
885
-        do_action('AHEE__EE_System__load_CPTs_and_session__complete');
886
-    }
887
-
888
-
889
-
890
-    /**
891
-     * load_controllers
892
-     * this is the best place to load any additional controllers that needs access to EE core.
893
-     * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
894
-     * time
895
-     *
896
-     * @access public
897
-     * @return void
898
-     */
899
-    public function load_controllers()
900
-    {
901
-        do_action('AHEE__EE_System__load_controllers__start');
902
-        // let's get it started
903
-        if ( ! is_admin() && ! EE_Maintenance_Mode::instance()->level()) {
904
-            do_action('AHEE__EE_System__load_controllers__load_front_controllers');
905
-            $this->registry->load_core('Front_Controller');
906
-        } else if ( ! EE_FRONT_AJAX) {
907
-            do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
908
-            EE_Registry::instance()->load_core('Admin');
909
-        }
910
-        do_action('AHEE__EE_System__load_controllers__complete');
911
-    }
912
-
913
-
914
-
915
-    /**
916
-     * core_loaded_and_ready
917
-     * all of the basic EE core should be loaded at this point and available regardless of M-Mode
918
-     *
919
-     * @access public
920
-     * @return void
921
-     */
922
-    public function core_loaded_and_ready()
923
-    {
924
-        $this->registry->load_core('Session');
925
-        do_action('AHEE__EE_System__core_loaded_and_ready');
926
-        // load_espresso_template_tags
927
-        if (is_readable(EE_PUBLIC . 'template_tags.php')) {
928
-            require_once(EE_PUBLIC . 'template_tags.php');
929
-        }
930
-        do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
931
-        $this->registry->create('EventEspresso\core\services\assets\Registry', array(), true);
932
-    }
933
-
934
-
935
-
936
-    /**
937
-     * initialize
938
-     * this is the best place to begin initializing client code
939
-     *
940
-     * @access public
941
-     * @return void
942
-     */
943
-    public function initialize()
944
-    {
945
-        do_action('AHEE__EE_System__initialize');
946
-    }
947
-
948
-
949
-
950
-    /**
951
-     * initialize_last
952
-     * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
953
-     * initialize has done so
954
-     *
955
-     * @access public
956
-     * @return void
957
-     */
958
-    public function initialize_last()
959
-    {
960
-        do_action('AHEE__EE_System__initialize_last');
961
-    }
962
-
963
-
964
-
965
-    /**
966
-     * set_hooks_for_shortcodes_modules_and_addons
967
-     * this is the best place for other systems to set callbacks for hooking into other parts of EE
968
-     * this happens at the very beginning of the wp_loaded hook point
969
-     *
970
-     * @access public
971
-     * @return void
972
-     */
973
-    public function set_hooks_for_shortcodes_modules_and_addons()
974
-    {
975
-        //		do_action( 'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons' );
976
-    }
977
-
978
-
979
-
980
-    /**
981
-     * do_not_cache
982
-     * sets no cache headers and defines no cache constants for WP plugins
983
-     *
984
-     * @access public
985
-     * @return void
986
-     */
987
-    public static function do_not_cache()
988
-    {
989
-        // set no cache constants
990
-        if ( ! defined('DONOTCACHEPAGE')) {
991
-            define('DONOTCACHEPAGE', true);
992
-        }
993
-        if ( ! defined('DONOTCACHCEOBJECT')) {
994
-            define('DONOTCACHCEOBJECT', true);
995
-        }
996
-        if ( ! defined('DONOTCACHEDB')) {
997
-            define('DONOTCACHEDB', true);
998
-        }
999
-        // add no cache headers
1000
-        add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1001
-        // plus a little extra for nginx and Google Chrome
1002
-        add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1003
-        // prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1004
-        remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1005
-    }
1006
-
1007
-
1008
-
1009
-    /**
1010
-     *    extra_nocache_headers
1011
-     *
1012
-     * @access    public
1013
-     * @param $headers
1014
-     * @return    array
1015
-     */
1016
-    public static function extra_nocache_headers($headers)
1017
-    {
1018
-        // for NGINX
1019
-        $headers['X-Accel-Expires'] = 0;
1020
-        // plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1021
-        $headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1022
-        return $headers;
1023
-    }
1024
-
1025
-
1026
-
1027
-    /**
1028
-     *    nocache_headers
1029
-     *
1030
-     * @access    public
1031
-     * @return    void
1032
-     */
1033
-    public static function nocache_headers()
1034
-    {
1035
-        nocache_headers();
1036
-    }
1037
-
1038
-
1039
-
1040
-    /**
1041
-     *    espresso_toolbar_items
1042
-     *
1043
-     * @access public
1044
-     * @param  WP_Admin_Bar $admin_bar
1045
-     * @return void
1046
-     */
1047
-    public function espresso_toolbar_items(WP_Admin_Bar $admin_bar)
1048
-    {
1049
-        // if in full M-Mode, or its an AJAX request, or user is NOT an admin
1050
-        if (
1051
-            defined('DOING_AJAX')
1052
-            || ! $this->registry->CAP->current_user_can('ee_read_ee', 'ee_admin_bar_menu_top_level')
1053
-            || EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance
1054
-        ) {
1055
-            return;
1056
-        }
1057
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1058
-        $menu_class = 'espresso_menu_item_class';
1059
-        //we don't use the constants EVENTS_ADMIN_URL or REG_ADMIN_URL
1060
-        //because they're only defined in each of their respective constructors
1061
-        //and this might be a frontend request, in which case they aren't available
1062
-        $events_admin_url = admin_url('admin.php?page=espresso_events');
1063
-        $reg_admin_url = admin_url('admin.php?page=espresso_registrations');
1064
-        $extensions_admin_url = admin_url('admin.php?page=espresso_packages');
1065
-        //Top Level
1066
-        $admin_bar->add_menu(array(
1067
-            'id'    => 'espresso-toolbar',
1068
-            'title' => '<span class="ee-icon ee-icon-ee-cup-thick ee-icon-size-20"></span><span class="ab-label">'
1069
-                       . _x('Event Espresso', 'admin bar menu group label', 'event_espresso')
1070
-                       . '</span>',
1071
-            'href'  => $events_admin_url,
1072
-            'meta'  => array(
1073
-                'title' => __('Event Espresso', 'event_espresso'),
1074
-                'class' => $menu_class . 'first',
1075
-            ),
1076
-        ));
1077
-        //Events
1078
-        if ($this->registry->CAP->current_user_can('ee_read_events', 'ee_admin_bar_menu_espresso-toolbar-events')) {
1079
-            $admin_bar->add_menu(array(
1080
-                'id'     => 'espresso-toolbar-events',
1081
-                'parent' => 'espresso-toolbar',
1082
-                'title'  => __('Events', 'event_espresso'),
1083
-                'href'   => $events_admin_url,
1084
-                'meta'   => array(
1085
-                    'title'  => __('Events', 'event_espresso'),
1086
-                    'target' => '',
1087
-                    'class'  => $menu_class,
1088
-                ),
1089
-            ));
1090
-        }
1091
-        if ($this->registry->CAP->current_user_can('ee_edit_events', 'ee_admin_bar_menu_espresso-toolbar-events-new')) {
1092
-            //Events Add New
1093
-            $admin_bar->add_menu(array(
1094
-                'id'     => 'espresso-toolbar-events-new',
1095
-                'parent' => 'espresso-toolbar-events',
1096
-                'title'  => __('Add New', 'event_espresso'),
1097
-                'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'create_new'), $events_admin_url),
1098
-                'meta'   => array(
1099
-                    'title'  => __('Add New', 'event_espresso'),
1100
-                    'target' => '',
1101
-                    'class'  => $menu_class,
1102
-                ),
1103
-            ));
1104
-        }
1105
-        if (is_single() && (get_post_type() === 'espresso_events')) {
1106
-            //Current post
1107
-            global $post;
1108
-            if ($this->registry->CAP->current_user_can('ee_edit_event',
1109
-                'ee_admin_bar_menu_espresso-toolbar-events-edit', $post->ID)
1110
-            ) {
1111
-                //Events Edit Current Event
1112
-                $admin_bar->add_menu(array(
1113
-                    'id'     => 'espresso-toolbar-events-edit',
1114
-                    'parent' => 'espresso-toolbar-events',
1115
-                    'title'  => __('Edit Event', 'event_espresso'),
1116
-                    'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'edit', 'post' => $post->ID),
1117
-                        $events_admin_url),
1118
-                    'meta'   => array(
1119
-                        'title'  => __('Edit Event', 'event_espresso'),
1120
-                        'target' => '',
1121
-                        'class'  => $menu_class,
1122
-                    ),
1123
-                ));
1124
-            }
1125
-        }
1126
-        //Events View
1127
-        if ($this->registry->CAP->current_user_can('ee_read_events',
1128
-            'ee_admin_bar_menu_espresso-toolbar-events-view')
1129
-        ) {
1130
-            $admin_bar->add_menu(array(
1131
-                'id'     => 'espresso-toolbar-events-view',
1132
-                'parent' => 'espresso-toolbar-events',
1133
-                'title'  => __('View', 'event_espresso'),
1134
-                'href'   => $events_admin_url,
1135
-                'meta'   => array(
1136
-                    'title'  => __('View', 'event_espresso'),
1137
-                    'target' => '',
1138
-                    'class'  => $menu_class,
1139
-                ),
1140
-            ));
1141
-        }
1142
-        if ($this->registry->CAP->current_user_can('ee_read_events', 'ee_admin_bar_menu_espresso-toolbar-events-all')) {
1143
-            //Events View All
1144
-            $admin_bar->add_menu(array(
1145
-                'id'     => 'espresso-toolbar-events-all',
1146
-                'parent' => 'espresso-toolbar-events-view',
1147
-                'title'  => __('All', 'event_espresso'),
1148
-                'href'   => $events_admin_url,
1149
-                'meta'   => array(
1150
-                    'title'  => __('All', 'event_espresso'),
1151
-                    'target' => '',
1152
-                    'class'  => $menu_class,
1153
-                ),
1154
-            ));
1155
-        }
1156
-        if ($this->registry->CAP->current_user_can('ee_read_events',
1157
-            'ee_admin_bar_menu_espresso-toolbar-events-today')
1158
-        ) {
1159
-            //Events View Today
1160
-            $admin_bar->add_menu(array(
1161
-                'id'     => 'espresso-toolbar-events-today',
1162
-                'parent' => 'espresso-toolbar-events-view',
1163
-                'title'  => __('Today', 'event_espresso'),
1164
-                'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'default', 'status' => 'today'),
1165
-                    $events_admin_url),
1166
-                'meta'   => array(
1167
-                    'title'  => __('Today', 'event_espresso'),
1168
-                    'target' => '',
1169
-                    'class'  => $menu_class,
1170
-                ),
1171
-            ));
1172
-        }
1173
-        if ($this->registry->CAP->current_user_can('ee_read_events',
1174
-            'ee_admin_bar_menu_espresso-toolbar-events-month')
1175
-        ) {
1176
-            //Events View This Month
1177
-            $admin_bar->add_menu(array(
1178
-                'id'     => 'espresso-toolbar-events-month',
1179
-                'parent' => 'espresso-toolbar-events-view',
1180
-                'title'  => __('This Month', 'event_espresso'),
1181
-                'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'default', 'status' => 'month'),
1182
-                    $events_admin_url),
1183
-                'meta'   => array(
1184
-                    'title'  => __('This Month', 'event_espresso'),
1185
-                    'target' => '',
1186
-                    'class'  => $menu_class,
1187
-                ),
1188
-            ));
1189
-        }
1190
-        //Registration Overview
1191
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1192
-            'ee_admin_bar_menu_espresso-toolbar-registrations')
1193
-        ) {
1194
-            $admin_bar->add_menu(array(
1195
-                'id'     => 'espresso-toolbar-registrations',
1196
-                'parent' => 'espresso-toolbar',
1197
-                'title'  => __('Registrations', 'event_espresso'),
1198
-                'href'   => $reg_admin_url,
1199
-                'meta'   => array(
1200
-                    'title'  => __('Registrations', 'event_espresso'),
1201
-                    'target' => '',
1202
-                    'class'  => $menu_class,
1203
-                ),
1204
-            ));
1205
-        }
1206
-        //Registration Overview Today
1207
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1208
-            'ee_admin_bar_menu_espresso-toolbar-registrations-today')
1209
-        ) {
1210
-            $admin_bar->add_menu(array(
1211
-                'id'     => 'espresso-toolbar-registrations-today',
1212
-                'parent' => 'espresso-toolbar-registrations',
1213
-                'title'  => __('Today', 'event_espresso'),
1214
-                'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'default', 'status' => 'today'),
1215
-                    $reg_admin_url),
1216
-                'meta'   => array(
1217
-                    'title'  => __('Today', 'event_espresso'),
1218
-                    'target' => '',
1219
-                    'class'  => $menu_class,
1220
-                ),
1221
-            ));
1222
-        }
1223
-        //Registration Overview Today Completed
1224
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1225
-            'ee_admin_bar_menu_espresso-toolbar-registrations-today-approved')
1226
-        ) {
1227
-            $admin_bar->add_menu(array(
1228
-                'id'     => 'espresso-toolbar-registrations-today-approved',
1229
-                'parent' => 'espresso-toolbar-registrations-today',
1230
-                'title'  => __('Approved', 'event_espresso'),
1231
-                'href'   => EEH_URL::add_query_args_and_nonce(array(
1232
-                    'action'      => 'default',
1233
-                    'status'      => 'today',
1234
-                    '_reg_status' => EEM_Registration::status_id_approved,
1235
-                ), $reg_admin_url),
1236
-                'meta'   => array(
1237
-                    'title'  => __('Approved', 'event_espresso'),
1238
-                    'target' => '',
1239
-                    'class'  => $menu_class,
1240
-                ),
1241
-            ));
1242
-        }
1243
-        //Registration Overview Today Pending\
1244
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1245
-            'ee_admin_bar_menu_espresso-toolbar-registrations-today-pending')
1246
-        ) {
1247
-            $admin_bar->add_menu(array(
1248
-                'id'     => 'espresso-toolbar-registrations-today-pending',
1249
-                'parent' => 'espresso-toolbar-registrations-today',
1250
-                'title'  => __('Pending', 'event_espresso'),
1251
-                'href'   => EEH_URL::add_query_args_and_nonce(array(
1252
-                    'action'     => 'default',
1253
-                    'status'     => 'today',
1254
-                    'reg_status' => EEM_Registration::status_id_pending_payment,
1255
-                ), $reg_admin_url),
1256
-                'meta'   => array(
1257
-                    'title'  => __('Pending Payment', 'event_espresso'),
1258
-                    'target' => '',
1259
-                    'class'  => $menu_class,
1260
-                ),
1261
-            ));
1262
-        }
1263
-        //Registration Overview Today Incomplete
1264
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1265
-            'ee_admin_bar_menu_espresso-toolbar-registrations-today-not-approved')
1266
-        ) {
1267
-            $admin_bar->add_menu(array(
1268
-                'id'     => 'espresso-toolbar-registrations-today-not-approved',
1269
-                'parent' => 'espresso-toolbar-registrations-today',
1270
-                'title'  => __('Not Approved', 'event_espresso'),
1271
-                'href'   => EEH_URL::add_query_args_and_nonce(array(
1272
-                    'action'      => 'default',
1273
-                    'status'      => 'today',
1274
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1275
-                ), $reg_admin_url),
1276
-                'meta'   => array(
1277
-                    'title'  => __('Not Approved', 'event_espresso'),
1278
-                    'target' => '',
1279
-                    'class'  => $menu_class,
1280
-                ),
1281
-            ));
1282
-        }
1283
-        //Registration Overview Today Incomplete
1284
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1285
-            'ee_admin_bar_menu_espresso-toolbar-registrations-today-cancelled')
1286
-        ) {
1287
-            $admin_bar->add_menu(array(
1288
-                'id'     => 'espresso-toolbar-registrations-today-cancelled',
1289
-                'parent' => 'espresso-toolbar-registrations-today',
1290
-                'title'  => __('Cancelled', 'event_espresso'),
1291
-                'href'   => EEH_URL::add_query_args_and_nonce(array(
1292
-                    'action'      => 'default',
1293
-                    'status'      => 'today',
1294
-                    '_reg_status' => EEM_Registration::status_id_cancelled,
1295
-                ), $reg_admin_url),
1296
-                'meta'   => array(
1297
-                    'title'  => __('Cancelled', 'event_espresso'),
1298
-                    'target' => '',
1299
-                    'class'  => $menu_class,
1300
-                ),
1301
-            ));
1302
-        }
1303
-        //Registration Overview This Month
1304
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1305
-            'ee_admin_bar_menu_espresso-toolbar-registrations-month')
1306
-        ) {
1307
-            $admin_bar->add_menu(array(
1308
-                'id'     => 'espresso-toolbar-registrations-month',
1309
-                'parent' => 'espresso-toolbar-registrations',
1310
-                'title'  => __('This Month', 'event_espresso'),
1311
-                'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'default', 'status' => 'month'),
1312
-                    $reg_admin_url),
1313
-                'meta'   => array(
1314
-                    'title'  => __('This Month', 'event_espresso'),
1315
-                    'target' => '',
1316
-                    'class'  => $menu_class,
1317
-                ),
1318
-            ));
1319
-        }
1320
-        //Registration Overview This Month Approved
1321
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1322
-            'ee_admin_bar_menu_espresso-toolbar-registrations-month-approved')
1323
-        ) {
1324
-            $admin_bar->add_menu(array(
1325
-                'id'     => 'espresso-toolbar-registrations-month-approved',
1326
-                'parent' => 'espresso-toolbar-registrations-month',
1327
-                'title'  => __('Approved', 'event_espresso'),
1328
-                'href'   => EEH_URL::add_query_args_and_nonce(array(
1329
-                    'action'      => 'default',
1330
-                    'status'      => 'month',
1331
-                    '_reg_status' => EEM_Registration::status_id_approved,
1332
-                ), $reg_admin_url),
1333
-                'meta'   => array(
1334
-                    'title'  => __('Approved', 'event_espresso'),
1335
-                    'target' => '',
1336
-                    'class'  => $menu_class,
1337
-                ),
1338
-            ));
1339
-        }
1340
-        //Registration Overview This Month Pending
1341
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1342
-            'ee_admin_bar_menu_espresso-toolbar-registrations-month-pending')
1343
-        ) {
1344
-            $admin_bar->add_menu(array(
1345
-                'id'     => 'espresso-toolbar-registrations-month-pending',
1346
-                'parent' => 'espresso-toolbar-registrations-month',
1347
-                'title'  => __('Pending', 'event_espresso'),
1348
-                'href'   => EEH_URL::add_query_args_and_nonce(array(
1349
-                    'action'      => 'default',
1350
-                    'status'      => 'month',
1351
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1352
-                ), $reg_admin_url),
1353
-                'meta'   => array(
1354
-                    'title'  => __('Pending', 'event_espresso'),
1355
-                    'target' => '',
1356
-                    'class'  => $menu_class,
1357
-                ),
1358
-            ));
1359
-        }
1360
-        //Registration Overview This Month Not Approved
1361
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1362
-            'ee_admin_bar_menu_espresso-toolbar-registrations-month-not-approved')
1363
-        ) {
1364
-            $admin_bar->add_menu(array(
1365
-                'id'     => 'espresso-toolbar-registrations-month-not-approved',
1366
-                'parent' => 'espresso-toolbar-registrations-month',
1367
-                'title'  => __('Not Approved', 'event_espresso'),
1368
-                'href'   => EEH_URL::add_query_args_and_nonce(array(
1369
-                    'action'      => 'default',
1370
-                    'status'      => 'month',
1371
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1372
-                ), $reg_admin_url),
1373
-                'meta'   => array(
1374
-                    'title'  => __('Not Approved', 'event_espresso'),
1375
-                    'target' => '',
1376
-                    'class'  => $menu_class,
1377
-                ),
1378
-            ));
1379
-        }
1380
-        //Registration Overview This Month Cancelled
1381
-        if ($this->registry->CAP->current_user_can('ee_read_registrations',
1382
-            'ee_admin_bar_menu_espresso-toolbar-registrations-month-cancelled')
1383
-        ) {
1384
-            $admin_bar->add_menu(array(
1385
-                'id'     => 'espresso-toolbar-registrations-month-cancelled',
1386
-                'parent' => 'espresso-toolbar-registrations-month',
1387
-                'title'  => __('Cancelled', 'event_espresso'),
1388
-                'href'   => EEH_URL::add_query_args_and_nonce(array(
1389
-                    'action'      => 'default',
1390
-                    'status'      => 'month',
1391
-                    '_reg_status' => EEM_Registration::status_id_cancelled,
1392
-                ), $reg_admin_url),
1393
-                'meta'   => array(
1394
-                    'title'  => __('Cancelled', 'event_espresso'),
1395
-                    'target' => '',
1396
-                    'class'  => $menu_class,
1397
-                ),
1398
-            ));
1399
-        }
1400
-        //Extensions & Services
1401
-        if ($this->registry->CAP->current_user_can('ee_read_ee',
1402
-            'ee_admin_bar_menu_espresso-toolbar-extensions-and-services')
1403
-        ) {
1404
-            $admin_bar->add_menu(array(
1405
-                'id'     => 'espresso-toolbar-extensions-and-services',
1406
-                'parent' => 'espresso-toolbar',
1407
-                'title'  => __('Extensions & Services', 'event_espresso'),
1408
-                'href'   => $extensions_admin_url,
1409
-                'meta'   => array(
1410
-                    'title'  => __('Extensions & Services', 'event_espresso'),
1411
-                    'target' => '',
1412
-                    'class'  => $menu_class,
1413
-                ),
1414
-            ));
1415
-        }
1416
-    }
1417
-
1418
-
1419
-
1420
-    /**
1421
-     * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1422
-     * never returned with the function.
1423
-     *
1424
-     * @param  array $exclude_array any existing pages being excluded are in this array.
1425
-     * @return array
1426
-     */
1427
-    public function remove_pages_from_wp_list_pages($exclude_array)
1428
-    {
1429
-        return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1430
-    }
26
+	/**
27
+	 * indicates this is a 'normal' request. Ie, not activation, nor upgrade, nor activation.
28
+	 * So examples of this would be a normal GET request on the frontend or backend, or a POST, etc
29
+	 */
30
+	const req_type_normal = 0;
31
+
32
+	/**
33
+	 * Indicates this is a brand new installation of EE so we should install
34
+	 * tables and default data etc
35
+	 */
36
+	const req_type_new_activation = 1;
37
+
38
+	/**
39
+	 * we've detected that EE has been reactivated (or EE was activated during maintenance mode,
40
+	 * and we just exited maintenance mode). We MUST check the database is setup properly
41
+	 * and that default data is setup too
42
+	 */
43
+	const req_type_reactivation = 2;
44
+
45
+	/**
46
+	 * indicates that EE has been upgraded since its previous request.
47
+	 * We may have data migration scripts to call and will want to trigger maintenance mode
48
+	 */
49
+	const req_type_upgrade = 3;
50
+
51
+	/**
52
+	 * TODO  will detect that EE has been DOWNGRADED. We probably don't want to run in this case...
53
+	 */
54
+	const req_type_downgrade = 4;
55
+
56
+	/**
57
+	 * @deprecated since version 4.6.0.dev.006
58
+	 * Now whenever a new_activation is detected the request type is still just
59
+	 * new_activation (same for reactivation, upgrade, downgrade etc), but if we'r ein maintenance mode
60
+	 * EE_System::initialize_db_if_no_migrations_required and EE_Addon::initialize_db_if_no_migrations_required
61
+	 * will instead enqueue that EE plugin's db initialization for when we're taken out of maintenance mode.
62
+	 * (Specifically, when the migration manager indicates migrations are finished
63
+	 * EE_Data_Migration_Manager::initialize_db_for_enqueued_ee_plugins() will be called)
64
+	 */
65
+	const req_type_activation_but_not_installed = 5;
66
+
67
+	/**
68
+	 * option prefix for recording the activation history (like core's "espresso_db_update") of addons
69
+	 */
70
+	const addon_activation_history_option_prefix = 'ee_addon_activation_history_';
71
+
72
+
73
+	/**
74
+	 * @var EE_System $_instance
75
+	 */
76
+	private static $_instance;
77
+
78
+	/**
79
+	 * @var EE_Registry $registry
80
+	 */
81
+	protected $registry;
82
+
83
+	/**
84
+	 * Stores which type of request this is, options being one of the constants on EE_System starting with req_type_*.
85
+	 * It can be a brand-new activation, a reactivation, an upgrade, a downgrade, or a normal request.
86
+	 *
87
+	 * @var int $_req_type
88
+	 */
89
+	private $_req_type;
90
+
91
+	/**
92
+	 * Whether or not there was a non-micro version change in EE core version during this request
93
+	 *
94
+	 * @var boolean $_major_version_change
95
+	 */
96
+	private $_major_version_change = false;
97
+
98
+
99
+
100
+	/**
101
+	 * @singleton method used to instantiate class object
102
+	 * @access    public
103
+	 * @param  EE_Registry $Registry
104
+	 * @return EE_System
105
+	 */
106
+	public static function instance(EE_Registry $Registry = null)
107
+	{
108
+		// check if class object is instantiated
109
+		if ( ! self::$_instance instanceof EE_System) {
110
+			self::$_instance = new self($Registry);
111
+		}
112
+		return self::$_instance;
113
+	}
114
+
115
+
116
+
117
+	/**
118
+	 * resets the instance and returns it
119
+	 *
120
+	 * @return EE_System
121
+	 */
122
+	public static function reset()
123
+	{
124
+		self::$_instance->_req_type = null;
125
+		//make sure none of the old hooks are left hanging around
126
+		remove_all_actions('AHEE__EE_System__perform_activations_upgrades_and_migrations');
127
+		//we need to reset the migration manager in order for it to detect DMSs properly
128
+		EE_Data_Migration_Manager::reset();
129
+		self::instance()->detect_activations_or_upgrades();
130
+		self::instance()->perform_activations_upgrades_and_migrations();
131
+		return self::instance();
132
+	}
133
+
134
+
135
+
136
+	/**
137
+	 *    sets hooks for running rest of system
138
+	 *    provides "AHEE__EE_System__construct__complete" hook for EE Addons to use as their starting point
139
+	 *    starting EE Addons from any other point may lead to problems
140
+	 *
141
+	 * @access private
142
+	 * @param  EE_Registry $Registry
143
+	 */
144
+	private function __construct(EE_Registry $Registry)
145
+	{
146
+		$this->registry = $Registry;
147
+		do_action('AHEE__EE_System__construct__begin', $this);
148
+		// allow addons to load first so that they can register autoloaders, set hooks for running DMS's, etc
149
+		add_action('AHEE__EE_Bootstrap__load_espresso_addons', array($this, 'load_espresso_addons'));
150
+		// when an ee addon is activated, we want to call the core hook(s) again
151
+		// because the newly-activated addon didn't get a chance to run at all
152
+		add_action('activate_plugin', array($this, 'load_espresso_addons'), 1);
153
+		// detect whether install or upgrade
154
+		add_action('AHEE__EE_Bootstrap__detect_activations_or_upgrades', array($this, 'detect_activations_or_upgrades'),
155
+			3);
156
+		// load EE_Config, EE_Textdomain, etc
157
+		add_action('AHEE__EE_Bootstrap__load_core_configuration', array($this, 'load_core_configuration'), 5);
158
+		// load EE_Config, EE_Textdomain, etc
159
+		add_action('AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets',
160
+			array($this, 'register_shortcodes_modules_and_widgets'), 7);
161
+		// you wanna get going? I wanna get going... let's get going!
162
+		add_action('AHEE__EE_Bootstrap__brew_espresso', array($this, 'brew_espresso'), 9);
163
+		//other housekeeping
164
+		//exclude EE critical pages from wp_list_pages
165
+		add_filter('wp_list_pages_excludes', array($this, 'remove_pages_from_wp_list_pages'), 10);
166
+		// ALL EE Addons should use the following hook point to attach their initial setup too
167
+		// it's extremely important for EE Addons to register any class autoloaders so that they can be available when the EE_Config loads
168
+		do_action('AHEE__EE_System__construct__complete', $this);
169
+	}
170
+
171
+
172
+
173
+	/**
174
+	 * load_espresso_addons
175
+	 * allow addons to load first so that they can set hooks for running DMS's, etc
176
+	 * this is hooked into both:
177
+	 *    'AHEE__EE_Bootstrap__load_core_configuration'
178
+	 *        which runs during the WP 'plugins_loaded' action at priority 5
179
+	 *    and the WP 'activate_plugin' hook point
180
+	 *
181
+	 * @access public
182
+	 * @return void
183
+	 * @throws EE_Error
184
+	 */
185
+	public function load_espresso_addons()
186
+	{
187
+		// set autoloaders for all of the classes implementing EEI_Plugin_API
188
+		// which provide helpers for EE plugin authors to more easily register certain components with EE.
189
+		EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
190
+		//load and setup EE_Capabilities
191
+		$this->registry->load_core('Capabilities');
192
+		//caps need to be initialized on every request so that capability maps are set.
193
+		//@see https://events.codebasehq.com/projects/event-espresso/tickets/8674
194
+		$this->registry->CAP->init_caps();
195
+		do_action('AHEE__EE_System__load_espresso_addons');
196
+		//if the WP API basic auth plugin isn't already loaded, load it now.
197
+		//We want it for mobile apps. Just include the entire plugin
198
+		//also, don't load the basic auth when a plugin is getting activated, because
199
+		//it could be the basic auth plugin, and it doesn't check if its methods are already defined
200
+		//and causes a fatal error
201
+		if (
202
+			! (isset($_GET['activate']) && $_GET['activate'] === 'true')
203
+			&& ! function_exists('json_basic_auth_handler')
204
+			&& ! function_exists('json_basic_auth_error')
205
+			&& ! (
206
+				isset($_GET['action'])
207
+				&& in_array($_GET['action'], array('activate', 'activate-selected'), true)
208
+			)
209
+		) {
210
+			include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
211
+		}
212
+		do_action('AHEE__EE_System__load_espresso_addons__complete');
213
+	}
214
+
215
+
216
+
217
+	/**
218
+	 * detect_activations_or_upgrades
219
+	 * Checks for activation or upgrade of core first;
220
+	 * then also checks if any registered addons have been activated or upgraded
221
+	 * This is hooked into 'AHEE__EE_Bootstrap__detect_activations_or_upgrades'
222
+	 * which runs during the WP 'plugins_loaded' action at priority 3
223
+	 *
224
+	 * @access public
225
+	 * @return void
226
+	 */
227
+	public function detect_activations_or_upgrades()
228
+	{
229
+		//first off: let's make sure to handle core
230
+		$this->detect_if_activation_or_upgrade();
231
+		foreach ($this->registry->addons as $addon) {
232
+			//detect teh request type for that addon
233
+			$addon->detect_activation_or_upgrade();
234
+		}
235
+	}
236
+
237
+
238
+
239
+	/**
240
+	 * detect_if_activation_or_upgrade
241
+	 * Takes care of detecting whether this is a brand new install or code upgrade,
242
+	 * and either setting up the DB or setting up maintenance mode etc.
243
+	 *
244
+	 * @access public
245
+	 * @return void
246
+	 */
247
+	public function detect_if_activation_or_upgrade()
248
+	{
249
+		do_action('AHEE__EE_System___detect_if_activation_or_upgrade__begin');
250
+		// load M-Mode class
251
+		$this->registry->load_core('Maintenance_Mode');
252
+		// check if db has been updated, or if its a brand-new installation
253
+		$espresso_db_update = $this->fix_espresso_db_upgrade_option();
254
+		$request_type = $this->detect_req_type($espresso_db_update);
255
+		//EEH_Debug_Tools::printr( $request_type, '$request_type', __FILE__, __LINE__ );
256
+		switch ($request_type) {
257
+			case EE_System::req_type_new_activation:
258
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__new_activation');
259
+				$this->_handle_core_version_change($espresso_db_update);
260
+				break;
261
+			case EE_System::req_type_reactivation:
262
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__reactivation');
263
+				$this->_handle_core_version_change($espresso_db_update);
264
+				break;
265
+			case EE_System::req_type_upgrade:
266
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__upgrade');
267
+				//migrations may be required now that we've upgraded
268
+				EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
269
+				$this->_handle_core_version_change($espresso_db_update);
270
+				//				echo "done upgrade";die;
271
+				break;
272
+			case EE_System::req_type_downgrade:
273
+				do_action('AHEE__EE_System__detect_if_activation_or_upgrade__downgrade');
274
+				//its possible migrations are no longer required
275
+				EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old();
276
+				$this->_handle_core_version_change($espresso_db_update);
277
+				break;
278
+			case EE_System::req_type_normal:
279
+			default:
280
+				//				$this->_maybe_redirect_to_ee_about();
281
+				break;
282
+		}
283
+		do_action('AHEE__EE_System__detect_if_activation_or_upgrade__complete');
284
+	}
285
+
286
+
287
+
288
+	/**
289
+	 * Updates the list of installed versions and sets hooks for
290
+	 * initializing the database later during the request
291
+	 *
292
+	 * @param array $espresso_db_update
293
+	 */
294
+	protected function _handle_core_version_change($espresso_db_update)
295
+	{
296
+		$this->update_list_of_installed_versions($espresso_db_update);
297
+		//get ready to verify the DB is ok (provided we aren't in maintenance mode, of course)
298
+		add_action('AHEE__EE_System__perform_activations_upgrades_and_migrations',
299
+			array($this, 'initialize_db_if_no_migrations_required'));
300
+	}
301
+
302
+
303
+
304
+	/**
305
+	 * standardizes the wp option 'espresso_db_upgrade' which actually stores
306
+	 * information about what versions of EE have been installed and activated,
307
+	 * NOT necessarily the state of the database
308
+	 *
309
+	 * @param mixed $espresso_db_update the value of the WordPress option.
310
+	 *                                            If not supplied, fetches it from the options table
311
+	 * @return array the correct value of 'espresso_db_upgrade', after saving it, if it needed correction
312
+	 */
313
+	private function fix_espresso_db_upgrade_option($espresso_db_update = null)
314
+	{
315
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__begin', $espresso_db_update);
316
+		if ( ! $espresso_db_update) {
317
+			$espresso_db_update = get_option('espresso_db_update');
318
+		}
319
+		// check that option is an array
320
+		if ( ! is_array($espresso_db_update)) {
321
+			// if option is FALSE, then it never existed
322
+			if ($espresso_db_update === false) {
323
+				// make $espresso_db_update an array and save option with autoload OFF
324
+				$espresso_db_update = array();
325
+				add_option('espresso_db_update', $espresso_db_update, '', 'no');
326
+			} else {
327
+				// option is NOT FALSE but also is NOT an array, so make it an array and save it
328
+				$espresso_db_update = array($espresso_db_update => array());
329
+				update_option('espresso_db_update', $espresso_db_update);
330
+			}
331
+		} else {
332
+			$corrected_db_update = array();
333
+			//if IS an array, but is it an array where KEYS are version numbers, and values are arrays?
334
+			foreach ($espresso_db_update as $should_be_version_string => $should_be_array) {
335
+				if (is_int($should_be_version_string) && ! is_array($should_be_array)) {
336
+					//the key is an int, and the value IS NOT an array
337
+					//so it must be numerically-indexed, where values are versions installed...
338
+					//fix it!
339
+					$version_string = $should_be_array;
340
+					$corrected_db_update[$version_string] = array('unknown-date');
341
+				} else {
342
+					//ok it checks out
343
+					$corrected_db_update[$should_be_version_string] = $should_be_array;
344
+				}
345
+			}
346
+			$espresso_db_update = $corrected_db_update;
347
+			update_option('espresso_db_update', $espresso_db_update);
348
+		}
349
+		do_action('FHEE__EE_System__manage_fix_espresso_db_upgrade_option__complete', $espresso_db_update);
350
+		return $espresso_db_update;
351
+	}
352
+
353
+
354
+
355
+	/**
356
+	 * Does the traditional work of setting up the plugin's database and adding default data.
357
+	 * If migration script/process did not exist, this is what would happen on every activation/reactivation/upgrade.
358
+	 * NOTE: if we're in maintenance mode (which would be the case if we detect there are data
359
+	 * migration scripts that need to be run and a version change happens), enqueues core for database initialization,
360
+	 * so that it will be done when migrations are finished
361
+	 *
362
+	 * @param boolean $initialize_addons_too if true, we double-check addons' database tables etc too;
363
+	 * @param boolean $verify_schema         if true will re-check the database tables have the correct schema.
364
+	 *                                       This is a resource-intensive job
365
+	 *                                       so we prefer to only do it when necessary
366
+	 * @return void
367
+	 * @throws EE_Error
368
+	 */
369
+	public function initialize_db_if_no_migrations_required($initialize_addons_too = false, $verify_schema = true)
370
+	{
371
+		$request_type = $this->detect_req_type();
372
+		//only initialize system if we're not in maintenance mode.
373
+		if (EE_Maintenance_Mode::instance()->level() !== EE_Maintenance_Mode::level_2_complete_maintenance) {
374
+			update_option('ee_flush_rewrite_rules', true);
375
+			if ($verify_schema) {
376
+				EEH_Activation::initialize_db_and_folders();
377
+			}
378
+			EEH_Activation::initialize_db_content();
379
+			EEH_Activation::system_initialization();
380
+			if ($initialize_addons_too) {
381
+				$this->initialize_addons();
382
+			}
383
+		} else {
384
+			EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for('Core');
385
+		}
386
+		if ($request_type === EE_System::req_type_new_activation
387
+			|| $request_type === EE_System::req_type_reactivation
388
+			|| (
389
+				$request_type === EE_System::req_type_upgrade
390
+				&& $this->is_major_version_change()
391
+			)
392
+		) {
393
+			add_action('AHEE__EE_System__initialize_last', array($this, 'redirect_to_about_ee'), 9);
394
+		}
395
+	}
396
+
397
+
398
+
399
+	/**
400
+	 * Initializes the db for all registered addons
401
+	 *
402
+	 * @throws EE_Error
403
+	 */
404
+	public function initialize_addons()
405
+	{
406
+		//foreach registered addon, make sure its db is up-to-date too
407
+		foreach ($this->registry->addons as $addon) {
408
+			$addon->initialize_db_if_no_migrations_required();
409
+		}
410
+	}
411
+
412
+
413
+
414
+	/**
415
+	 * Adds the current code version to the saved wp option which stores a list of all ee versions ever installed.
416
+	 *
417
+	 * @param    array  $version_history
418
+	 * @param    string $current_version_to_add version to be added to the version history
419
+	 * @return    boolean success as to whether or not this option was changed
420
+	 */
421
+	public function update_list_of_installed_versions($version_history = null, $current_version_to_add = null)
422
+	{
423
+		if ( ! $version_history) {
424
+			$version_history = $this->fix_espresso_db_upgrade_option($version_history);
425
+		}
426
+		if ($current_version_to_add === null) {
427
+			$current_version_to_add = espresso_version();
428
+		}
429
+		$version_history[$current_version_to_add][] = date('Y-m-d H:i:s', time());
430
+		// re-save
431
+		return update_option('espresso_db_update', $version_history);
432
+	}
433
+
434
+
435
+
436
+	/**
437
+	 * Detects if the current version indicated in the has existed in the list of
438
+	 * previously-installed versions of EE (espresso_db_update). Does NOT modify it (ie, no side-effect)
439
+	 *
440
+	 * @param array $espresso_db_update array from the wp option stored under the name 'espresso_db_update'.
441
+	 *                                  If not supplied, fetches it from the options table.
442
+	 *                                  Also, caches its result so later parts of the code can also know whether
443
+	 *                                  there's been an update or not. This way we can add the current version to
444
+	 *                                  espresso_db_update, but still know if this is a new install or not
445
+	 * @return int one of the constants on EE_System::req_type_
446
+	 */
447
+	public function detect_req_type($espresso_db_update = null)
448
+	{
449
+		if ($this->_req_type === null) {
450
+			$espresso_db_update = ! empty($espresso_db_update) ? $espresso_db_update
451
+				: $this->fix_espresso_db_upgrade_option();
452
+			$this->_req_type = EE_System::detect_req_type_given_activation_history($espresso_db_update,
453
+				'ee_espresso_activation', espresso_version());
454
+			$this->_major_version_change = $this->_detect_major_version_change($espresso_db_update);
455
+		}
456
+		return $this->_req_type;
457
+	}
458
+
459
+
460
+
461
+	/**
462
+	 * Returns whether or not there was a non-micro version change (ie, change in either
463
+	 * the first or second number in the version. Eg 4.9.0.rc.001 to 4.10.0.rc.000,
464
+	 * but not 4.9.0.rc.0001 to 4.9.1.rc.0001
465
+	 *
466
+	 * @param $activation_history
467
+	 * @return bool
468
+	 */
469
+	protected function _detect_major_version_change($activation_history)
470
+	{
471
+		$previous_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history);
472
+		$previous_version_parts = explode('.', $previous_version);
473
+		$current_version_parts = explode('.', espresso_version());
474
+		return isset($previous_version_parts[0], $previous_version_parts[1], $current_version_parts[0], $current_version_parts[1])
475
+			   && ($previous_version_parts[0] !== $current_version_parts[0]
476
+				   || $previous_version_parts[1] !== $current_version_parts[1]
477
+			   );
478
+	}
479
+
480
+
481
+
482
+	/**
483
+	 * Returns true if either the major or minor version of EE changed during this request.
484
+	 * Eg 4.9.0.rc.001 to 4.10.0.rc.000, but not 4.9.0.rc.0001 to 4.9.1.rc.0001
485
+	 *
486
+	 * @return bool
487
+	 */
488
+	public function is_major_version_change()
489
+	{
490
+		return $this->_major_version_change;
491
+	}
492
+
493
+
494
+
495
+	/**
496
+	 * Determines the request type for any ee addon, given three piece of info: the current array of activation
497
+	 * histories (for core that' 'espresso_db_update' wp option); the name of the WordPress option which is temporarily
498
+	 * set upon activation of the plugin (for core it's 'ee_espresso_activation'); and the version that this plugin was
499
+	 * just activated to (for core that will always be espresso_version())
500
+	 *
501
+	 * @param array  $activation_history_for_addon     the option's value which stores the activation history for this
502
+	 *                                                 ee plugin. for core that's 'espresso_db_update'
503
+	 * @param string $activation_indicator_option_name the name of the WordPress option that is temporarily set to
504
+	 *                                                 indicate that this plugin was just activated
505
+	 * @param string $version_to_upgrade_to            the version that was just upgraded to (for core that will be
506
+	 *                                                 espresso_version())
507
+	 * @return int one of the constants on EE_System::req_type_*
508
+	 */
509
+	public static function detect_req_type_given_activation_history(
510
+		$activation_history_for_addon,
511
+		$activation_indicator_option_name,
512
+		$version_to_upgrade_to
513
+	) {
514
+		$version_is_higher = self::_new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to);
515
+		if ($activation_history_for_addon) {
516
+			//it exists, so this isn't a completely new install
517
+			//check if this version already in that list of previously installed versions
518
+			if ( ! isset($activation_history_for_addon[$version_to_upgrade_to])) {
519
+				//it a version we haven't seen before
520
+				if ($version_is_higher === 1) {
521
+					$req_type = EE_System::req_type_upgrade;
522
+				} else {
523
+					$req_type = EE_System::req_type_downgrade;
524
+				}
525
+				delete_option($activation_indicator_option_name);
526
+			} else {
527
+				// its not an update. maybe a reactivation?
528
+				if (get_option($activation_indicator_option_name, false)) {
529
+					if ($version_is_higher === -1) {
530
+						$req_type = EE_System::req_type_downgrade;
531
+					} elseif ($version_is_higher === 0) {
532
+						//we've seen this version before, but it's an activation. must be a reactivation
533
+						$req_type = EE_System::req_type_reactivation;
534
+					} else {//$version_is_higher === 1
535
+						$req_type = EE_System::req_type_upgrade;
536
+					}
537
+					delete_option($activation_indicator_option_name);
538
+				} else {
539
+					//we've seen this version before and the activation indicate doesn't show it was just activated
540
+					if ($version_is_higher === -1) {
541
+						$req_type = EE_System::req_type_downgrade;
542
+					} elseif ($version_is_higher === 0) {
543
+						//we've seen this version before and it's not an activation. its normal request
544
+						$req_type = EE_System::req_type_normal;
545
+					} else {//$version_is_higher === 1
546
+						$req_type = EE_System::req_type_upgrade;
547
+					}
548
+				}
549
+			}
550
+		} else {
551
+			//brand new install
552
+			$req_type = EE_System::req_type_new_activation;
553
+			delete_option($activation_indicator_option_name);
554
+		}
555
+		return $req_type;
556
+	}
557
+
558
+
559
+
560
+	/**
561
+	 * Detects if the $version_to_upgrade_to is higher than the most recent version in
562
+	 * the $activation_history_for_addon
563
+	 *
564
+	 * @param array  $activation_history_for_addon (keys are versions, values are arrays of times activated,
565
+	 *                                             sometimes containing 'unknown-date'
566
+	 * @param string $version_to_upgrade_to        (current version)
567
+	 * @return int results of version_compare( $version_to_upgrade_to, $most_recently_active_version ).
568
+	 *                                             ie, -1 if $version_to_upgrade_to is LOWER (downgrade);
569
+	 *                                             0 if $version_to_upgrade_to MATCHES (reactivation or normal request);
570
+	 *                                             1 if $version_to_upgrade_to is HIGHER (upgrade) ;
571
+	 */
572
+	protected static function _new_version_is_higher($activation_history_for_addon, $version_to_upgrade_to)
573
+	{
574
+		//find the most recently-activated version
575
+		$most_recently_active_version = EE_System::_get_most_recently_active_version_from_activation_history($activation_history_for_addon);
576
+		return version_compare($version_to_upgrade_to, $most_recently_active_version);
577
+	}
578
+
579
+
580
+
581
+	/**
582
+	 * Gets the most recently active version listed in the activation history,
583
+	 * and if none are found (ie, it's a brand new install) returns '0.0.0.dev.000'.
584
+	 *
585
+	 * @param array $activation_history  (keys are versions, values are arrays of times activated,
586
+	 *                                   sometimes containing 'unknown-date'
587
+	 * @return string
588
+	 */
589
+	protected static function _get_most_recently_active_version_from_activation_history($activation_history)
590
+	{
591
+		$most_recently_active_version_activation = '1970-01-01 00:00:00';
592
+		$most_recently_active_version = '0.0.0.dev.000';
593
+		if (is_array($activation_history)) {
594
+			foreach ($activation_history as $version => $times_activated) {
595
+				//check there is a record of when this version was activated. Otherwise,
596
+				//mark it as unknown
597
+				if ( ! $times_activated) {
598
+					$times_activated = array('unknown-date');
599
+				}
600
+				if (is_string($times_activated)) {
601
+					$times_activated = array($times_activated);
602
+				}
603
+				foreach ($times_activated as $an_activation) {
604
+					if ($an_activation !== 'unknown-date' && $an_activation > $most_recently_active_version_activation) {
605
+						$most_recently_active_version = $version;
606
+						$most_recently_active_version_activation = $an_activation === 'unknown-date'
607
+							? '1970-01-01 00:00:00' : $an_activation;
608
+					}
609
+				}
610
+			}
611
+		}
612
+		return $most_recently_active_version;
613
+	}
614
+
615
+
616
+
617
+	/**
618
+	 * This redirects to the about EE page after activation
619
+	 *
620
+	 * @return void
621
+	 */
622
+	public function redirect_to_about_ee()
623
+	{
624
+		$notices = EE_Error::get_notices(false);
625
+		//if current user is an admin and it's not an ajax or rest request
626
+		if (
627
+			! (defined('DOING_AJAX') && DOING_AJAX)
628
+			&& ! (defined('REST_REQUEST') && REST_REQUEST)
629
+			&& ! isset($notices['errors'])
630
+			&& apply_filters(
631
+				'FHEE__EE_System__redirect_to_about_ee__do_redirect',
632
+				$this->registry->CAP->current_user_can('manage_options', 'espresso_about_default')
633
+			)
634
+		) {
635
+			$query_params = array('page' => 'espresso_about');
636
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_new_activation) {
637
+				$query_params['new_activation'] = true;
638
+			}
639
+			if (EE_System::instance()->detect_req_type() === EE_System::req_type_reactivation) {
640
+				$query_params['reactivation'] = true;
641
+			}
642
+			$url = add_query_arg($query_params, admin_url('admin.php'));
643
+			wp_safe_redirect($url);
644
+			exit();
645
+		}
646
+	}
647
+
648
+
649
+
650
+	/**
651
+	 * load_core_configuration
652
+	 * this is hooked into 'AHEE__EE_Bootstrap__load_core_configuration'
653
+	 * which runs during the WP 'plugins_loaded' action at priority 5
654
+	 *
655
+	 * @return void
656
+	 * @throws \ReflectionException
657
+	 */
658
+	public function load_core_configuration()
659
+	{
660
+		do_action('AHEE__EE_System__load_core_configuration__begin', $this);
661
+		$this->registry->load_core('EE_Load_Textdomain');
662
+		//load textdomain
663
+		EE_Load_Textdomain::load_textdomain();
664
+		// load and setup EE_Config and EE_Network_Config
665
+		$this->registry->load_core('Config');
666
+		$this->registry->load_core('Network_Config');
667
+		// setup autoloaders
668
+		// enable logging?
669
+		if ($this->registry->CFG->admin->use_full_logging) {
670
+			$this->registry->load_core('Log');
671
+		}
672
+		// check for activation errors
673
+		$activation_errors = get_option('ee_plugin_activation_errors', false);
674
+		if ($activation_errors) {
675
+			EE_Error::add_error($activation_errors, __FILE__, __FUNCTION__, __LINE__);
676
+			update_option('ee_plugin_activation_errors', false);
677
+		}
678
+		// get model names
679
+		$this->_parse_model_names();
680
+		//load caf stuff a chance to play during the activation process too.
681
+		$this->_maybe_brew_regular();
682
+		do_action('AHEE__EE_System__load_core_configuration__complete', $this);
683
+	}
684
+
685
+
686
+
687
+	/**
688
+	 * cycles through all of the models/*.model.php files, and assembles an array of model names
689
+	 *
690
+	 * @return void
691
+	 * @throws ReflectionException
692
+	 */
693
+	private function _parse_model_names()
694
+	{
695
+		//get all the files in the EE_MODELS folder that end in .model.php
696
+		$models = glob(EE_MODELS . '*.model.php');
697
+		$model_names = array();
698
+		$non_abstract_db_models = array();
699
+		foreach ($models as $model) {
700
+			// get model classname
701
+			$classname = EEH_File::get_classname_from_filepath_with_standard_filename($model);
702
+			$short_name = str_replace('EEM_', '', $classname);
703
+			$reflectionClass = new ReflectionClass($classname);
704
+			if ($reflectionClass->isSubclassOf('EEM_Base') && ! $reflectionClass->isAbstract()) {
705
+				$non_abstract_db_models[$short_name] = $classname;
706
+			}
707
+			$model_names[$short_name] = $classname;
708
+		}
709
+		$this->registry->models = apply_filters('FHEE__EE_System__parse_model_names', $model_names);
710
+		$this->registry->non_abstract_db_models = apply_filters('FHEE__EE_System__parse_implemented_model_names',
711
+			$non_abstract_db_models);
712
+	}
713
+
714
+
715
+
716
+	/**
717
+	 * The purpose of this method is to simply check for a file named "caffeinated/brewing_regular.php" for any hooks
718
+	 * that need to be setup before our EE_System launches.
719
+	 *
720
+	 * @return void
721
+	 */
722
+	private function _maybe_brew_regular()
723
+	{
724
+		if (( ! defined('EE_DECAF') || EE_DECAF !== true) && is_readable(EE_CAFF_PATH . 'brewing_regular.php')) {
725
+			require_once EE_CAFF_PATH . 'brewing_regular.php';
726
+		}
727
+	}
728
+
729
+
730
+
731
+	/**
732
+	 * register_shortcodes_modules_and_widgets
733
+	 * generate lists of shortcodes and modules, then verify paths and classes
734
+	 * This is hooked into 'AHEE__EE_Bootstrap__register_shortcodes_modules_and_widgets'
735
+	 * which runs during the WP 'plugins_loaded' action at priority 7
736
+	 *
737
+	 * @access public
738
+	 * @return void
739
+	 */
740
+	public function register_shortcodes_modules_and_widgets()
741
+	{
742
+		try {
743
+			// load, register, and add shortcodes the new way
744
+			new ShortcodesManager(
745
+			// and the old way, but we'll put it under control of the new system
746
+				EE_Config::getLegacyShortcodesManager()
747
+			);
748
+		} catch (Exception $exception) {
749
+			new ExceptionStackTraceDisplay($exception);
750
+		}
751
+		do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets');
752
+		// check for addons using old hook point
753
+		if (has_action('AHEE__EE_System__register_shortcodes_modules_and_addons')) {
754
+			$this->_incompatible_addon_error();
755
+		}
756
+	}
757
+
758
+
759
+
760
+	/**
761
+	 * _incompatible_addon_error
762
+	 *
763
+	 * @access public
764
+	 * @return void
765
+	 */
766
+	private function _incompatible_addon_error()
767
+	{
768
+		// get array of classes hooking into here
769
+		$class_names = EEH_Class_Tools::get_class_names_for_all_callbacks_on_hook('AHEE__EE_System__register_shortcodes_modules_and_addons');
770
+		if ( ! empty($class_names)) {
771
+			$msg = __('The following plugins, addons, or modules appear to be incompatible with this version of Event Espresso and were automatically deactivated to avoid fatal errors:',
772
+				'event_espresso');
773
+			$msg .= '<ul>';
774
+			foreach ($class_names as $class_name) {
775
+				$msg .= '<li><b>Event Espresso - ' . str_replace(array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
776
+						$class_name) . '</b></li>';
777
+			}
778
+			$msg .= '</ul>';
779
+			$msg .= __('Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
780
+				'event_espresso');
781
+			// save list of incompatible addons to wp-options for later use
782
+			add_option('ee_incompatible_addons', $class_names, '', 'no');
783
+			if (is_admin()) {
784
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
785
+			}
786
+		}
787
+	}
788
+
789
+
790
+
791
+	/**
792
+	 * brew_espresso
793
+	 * begins the process of setting hooks for initializing EE in the correct order
794
+	 * This is happening on the 'AHEE__EE_Bootstrap__brew_espresso' hook point
795
+	 * which runs during the WP 'plugins_loaded' action at priority 9
796
+	 *
797
+	 * @return void
798
+	 */
799
+	public function brew_espresso()
800
+	{
801
+		do_action('AHEE__EE_System__brew_espresso__begin', $this);
802
+		// load some final core systems
803
+		add_action('init', array($this, 'set_hooks_for_core'), 1);
804
+		add_action('init', array($this, 'perform_activations_upgrades_and_migrations'), 3);
805
+		add_action('init', array($this, 'load_CPTs_and_session'), 5);
806
+		add_action('init', array($this, 'load_controllers'), 7);
807
+		add_action('init', array($this, 'core_loaded_and_ready'), 9);
808
+		add_action('init', array($this, 'initialize'), 10);
809
+		add_action('init', array($this, 'initialize_last'), 100);
810
+		add_action('admin_bar_menu', array($this, 'espresso_toolbar_items'), 100);
811
+		if (is_admin() && apply_filters('FHEE__EE_System__brew_espresso__load_pue', true)) {
812
+			// pew pew pew
813
+			$this->registry->load_core('PUE');
814
+			do_action('AHEE__EE_System__brew_espresso__after_pue_init');
815
+		}
816
+		do_action('AHEE__EE_System__brew_espresso__complete', $this);
817
+	}
818
+
819
+
820
+
821
+	/**
822
+	 *    set_hooks_for_core
823
+	 *
824
+	 * @access public
825
+	 * @return    void
826
+	 */
827
+	public function set_hooks_for_core()
828
+	{
829
+		$this->_deactivate_incompatible_addons();
830
+		do_action('AHEE__EE_System__set_hooks_for_core');
831
+	}
832
+
833
+
834
+
835
+	/**
836
+	 * Using the information gathered in EE_System::_incompatible_addon_error,
837
+	 * deactivates any addons considered incompatible with the current version of EE
838
+	 */
839
+	private function _deactivate_incompatible_addons()
840
+	{
841
+		$incompatible_addons = get_option('ee_incompatible_addons', array());
842
+		if ( ! empty($incompatible_addons)) {
843
+			$active_plugins = get_option('active_plugins', array());
844
+			foreach ($active_plugins as $active_plugin) {
845
+				foreach ($incompatible_addons as $incompatible_addon) {
846
+					if (strpos($active_plugin, $incompatible_addon) !== false) {
847
+						unset($_GET['activate']);
848
+						espresso_deactivate_plugin($active_plugin);
849
+					}
850
+				}
851
+			}
852
+		}
853
+	}
854
+
855
+
856
+
857
+	/**
858
+	 *    perform_activations_upgrades_and_migrations
859
+	 *
860
+	 * @access public
861
+	 * @return    void
862
+	 */
863
+	public function perform_activations_upgrades_and_migrations()
864
+	{
865
+		//first check if we had previously attempted to setup EE's directories but failed
866
+		if (EEH_Activation::upload_directories_incomplete()) {
867
+			EEH_Activation::create_upload_directories();
868
+		}
869
+		do_action('AHEE__EE_System__perform_activations_upgrades_and_migrations');
870
+	}
871
+
872
+
873
+
874
+	/**
875
+	 *    load_CPTs_and_session
876
+	 *
877
+	 * @access public
878
+	 * @return    void
879
+	 */
880
+	public function load_CPTs_and_session()
881
+	{
882
+		do_action('AHEE__EE_System__load_CPTs_and_session__start');
883
+		// register Custom Post Types
884
+		$this->registry->load_core('Register_CPTs');
885
+		do_action('AHEE__EE_System__load_CPTs_and_session__complete');
886
+	}
887
+
888
+
889
+
890
+	/**
891
+	 * load_controllers
892
+	 * this is the best place to load any additional controllers that needs access to EE core.
893
+	 * it is expected that all basic core EE systems, that are not dependant on the current request are loaded at this
894
+	 * time
895
+	 *
896
+	 * @access public
897
+	 * @return void
898
+	 */
899
+	public function load_controllers()
900
+	{
901
+		do_action('AHEE__EE_System__load_controllers__start');
902
+		// let's get it started
903
+		if ( ! is_admin() && ! EE_Maintenance_Mode::instance()->level()) {
904
+			do_action('AHEE__EE_System__load_controllers__load_front_controllers');
905
+			$this->registry->load_core('Front_Controller');
906
+		} else if ( ! EE_FRONT_AJAX) {
907
+			do_action('AHEE__EE_System__load_controllers__load_admin_controllers');
908
+			EE_Registry::instance()->load_core('Admin');
909
+		}
910
+		do_action('AHEE__EE_System__load_controllers__complete');
911
+	}
912
+
913
+
914
+
915
+	/**
916
+	 * core_loaded_and_ready
917
+	 * all of the basic EE core should be loaded at this point and available regardless of M-Mode
918
+	 *
919
+	 * @access public
920
+	 * @return void
921
+	 */
922
+	public function core_loaded_and_ready()
923
+	{
924
+		$this->registry->load_core('Session');
925
+		do_action('AHEE__EE_System__core_loaded_and_ready');
926
+		// load_espresso_template_tags
927
+		if (is_readable(EE_PUBLIC . 'template_tags.php')) {
928
+			require_once(EE_PUBLIC . 'template_tags.php');
929
+		}
930
+		do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
931
+		$this->registry->create('EventEspresso\core\services\assets\Registry', array(), true);
932
+	}
933
+
934
+
935
+
936
+	/**
937
+	 * initialize
938
+	 * this is the best place to begin initializing client code
939
+	 *
940
+	 * @access public
941
+	 * @return void
942
+	 */
943
+	public function initialize()
944
+	{
945
+		do_action('AHEE__EE_System__initialize');
946
+	}
947
+
948
+
949
+
950
+	/**
951
+	 * initialize_last
952
+	 * this is run really late during the WP init hook point, and ensures that mostly everything else that needs to
953
+	 * initialize has done so
954
+	 *
955
+	 * @access public
956
+	 * @return void
957
+	 */
958
+	public function initialize_last()
959
+	{
960
+		do_action('AHEE__EE_System__initialize_last');
961
+	}
962
+
963
+
964
+
965
+	/**
966
+	 * set_hooks_for_shortcodes_modules_and_addons
967
+	 * this is the best place for other systems to set callbacks for hooking into other parts of EE
968
+	 * this happens at the very beginning of the wp_loaded hook point
969
+	 *
970
+	 * @access public
971
+	 * @return void
972
+	 */
973
+	public function set_hooks_for_shortcodes_modules_and_addons()
974
+	{
975
+		//		do_action( 'AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons' );
976
+	}
977
+
978
+
979
+
980
+	/**
981
+	 * do_not_cache
982
+	 * sets no cache headers and defines no cache constants for WP plugins
983
+	 *
984
+	 * @access public
985
+	 * @return void
986
+	 */
987
+	public static function do_not_cache()
988
+	{
989
+		// set no cache constants
990
+		if ( ! defined('DONOTCACHEPAGE')) {
991
+			define('DONOTCACHEPAGE', true);
992
+		}
993
+		if ( ! defined('DONOTCACHCEOBJECT')) {
994
+			define('DONOTCACHCEOBJECT', true);
995
+		}
996
+		if ( ! defined('DONOTCACHEDB')) {
997
+			define('DONOTCACHEDB', true);
998
+		}
999
+		// add no cache headers
1000
+		add_action('send_headers', array('EE_System', 'nocache_headers'), 10);
1001
+		// plus a little extra for nginx and Google Chrome
1002
+		add_filter('nocache_headers', array('EE_System', 'extra_nocache_headers'), 10, 1);
1003
+		// prevent browsers from prefetching of the rel='next' link, because it may contain content that interferes with the registration process
1004
+		remove_action('wp_head', 'adjacent_posts_rel_link_wp_head');
1005
+	}
1006
+
1007
+
1008
+
1009
+	/**
1010
+	 *    extra_nocache_headers
1011
+	 *
1012
+	 * @access    public
1013
+	 * @param $headers
1014
+	 * @return    array
1015
+	 */
1016
+	public static function extra_nocache_headers($headers)
1017
+	{
1018
+		// for NGINX
1019
+		$headers['X-Accel-Expires'] = 0;
1020
+		// plus extra for Google Chrome since it doesn't seem to respect "no-cache", but WILL respect "no-store"
1021
+		$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
1022
+		return $headers;
1023
+	}
1024
+
1025
+
1026
+
1027
+	/**
1028
+	 *    nocache_headers
1029
+	 *
1030
+	 * @access    public
1031
+	 * @return    void
1032
+	 */
1033
+	public static function nocache_headers()
1034
+	{
1035
+		nocache_headers();
1036
+	}
1037
+
1038
+
1039
+
1040
+	/**
1041
+	 *    espresso_toolbar_items
1042
+	 *
1043
+	 * @access public
1044
+	 * @param  WP_Admin_Bar $admin_bar
1045
+	 * @return void
1046
+	 */
1047
+	public function espresso_toolbar_items(WP_Admin_Bar $admin_bar)
1048
+	{
1049
+		// if in full M-Mode, or its an AJAX request, or user is NOT an admin
1050
+		if (
1051
+			defined('DOING_AJAX')
1052
+			|| ! $this->registry->CAP->current_user_can('ee_read_ee', 'ee_admin_bar_menu_top_level')
1053
+			|| EE_Maintenance_Mode::instance()->level() === EE_Maintenance_Mode::level_2_complete_maintenance
1054
+		) {
1055
+			return;
1056
+		}
1057
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1058
+		$menu_class = 'espresso_menu_item_class';
1059
+		//we don't use the constants EVENTS_ADMIN_URL or REG_ADMIN_URL
1060
+		//because they're only defined in each of their respective constructors
1061
+		//and this might be a frontend request, in which case they aren't available
1062
+		$events_admin_url = admin_url('admin.php?page=espresso_events');
1063
+		$reg_admin_url = admin_url('admin.php?page=espresso_registrations');
1064
+		$extensions_admin_url = admin_url('admin.php?page=espresso_packages');
1065
+		//Top Level
1066
+		$admin_bar->add_menu(array(
1067
+			'id'    => 'espresso-toolbar',
1068
+			'title' => '<span class="ee-icon ee-icon-ee-cup-thick ee-icon-size-20"></span><span class="ab-label">'
1069
+					   . _x('Event Espresso', 'admin bar menu group label', 'event_espresso')
1070
+					   . '</span>',
1071
+			'href'  => $events_admin_url,
1072
+			'meta'  => array(
1073
+				'title' => __('Event Espresso', 'event_espresso'),
1074
+				'class' => $menu_class . 'first',
1075
+			),
1076
+		));
1077
+		//Events
1078
+		if ($this->registry->CAP->current_user_can('ee_read_events', 'ee_admin_bar_menu_espresso-toolbar-events')) {
1079
+			$admin_bar->add_menu(array(
1080
+				'id'     => 'espresso-toolbar-events',
1081
+				'parent' => 'espresso-toolbar',
1082
+				'title'  => __('Events', 'event_espresso'),
1083
+				'href'   => $events_admin_url,
1084
+				'meta'   => array(
1085
+					'title'  => __('Events', 'event_espresso'),
1086
+					'target' => '',
1087
+					'class'  => $menu_class,
1088
+				),
1089
+			));
1090
+		}
1091
+		if ($this->registry->CAP->current_user_can('ee_edit_events', 'ee_admin_bar_menu_espresso-toolbar-events-new')) {
1092
+			//Events Add New
1093
+			$admin_bar->add_menu(array(
1094
+				'id'     => 'espresso-toolbar-events-new',
1095
+				'parent' => 'espresso-toolbar-events',
1096
+				'title'  => __('Add New', 'event_espresso'),
1097
+				'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'create_new'), $events_admin_url),
1098
+				'meta'   => array(
1099
+					'title'  => __('Add New', 'event_espresso'),
1100
+					'target' => '',
1101
+					'class'  => $menu_class,
1102
+				),
1103
+			));
1104
+		}
1105
+		if (is_single() && (get_post_type() === 'espresso_events')) {
1106
+			//Current post
1107
+			global $post;
1108
+			if ($this->registry->CAP->current_user_can('ee_edit_event',
1109
+				'ee_admin_bar_menu_espresso-toolbar-events-edit', $post->ID)
1110
+			) {
1111
+				//Events Edit Current Event
1112
+				$admin_bar->add_menu(array(
1113
+					'id'     => 'espresso-toolbar-events-edit',
1114
+					'parent' => 'espresso-toolbar-events',
1115
+					'title'  => __('Edit Event', 'event_espresso'),
1116
+					'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'edit', 'post' => $post->ID),
1117
+						$events_admin_url),
1118
+					'meta'   => array(
1119
+						'title'  => __('Edit Event', 'event_espresso'),
1120
+						'target' => '',
1121
+						'class'  => $menu_class,
1122
+					),
1123
+				));
1124
+			}
1125
+		}
1126
+		//Events View
1127
+		if ($this->registry->CAP->current_user_can('ee_read_events',
1128
+			'ee_admin_bar_menu_espresso-toolbar-events-view')
1129
+		) {
1130
+			$admin_bar->add_menu(array(
1131
+				'id'     => 'espresso-toolbar-events-view',
1132
+				'parent' => 'espresso-toolbar-events',
1133
+				'title'  => __('View', 'event_espresso'),
1134
+				'href'   => $events_admin_url,
1135
+				'meta'   => array(
1136
+					'title'  => __('View', 'event_espresso'),
1137
+					'target' => '',
1138
+					'class'  => $menu_class,
1139
+				),
1140
+			));
1141
+		}
1142
+		if ($this->registry->CAP->current_user_can('ee_read_events', 'ee_admin_bar_menu_espresso-toolbar-events-all')) {
1143
+			//Events View All
1144
+			$admin_bar->add_menu(array(
1145
+				'id'     => 'espresso-toolbar-events-all',
1146
+				'parent' => 'espresso-toolbar-events-view',
1147
+				'title'  => __('All', 'event_espresso'),
1148
+				'href'   => $events_admin_url,
1149
+				'meta'   => array(
1150
+					'title'  => __('All', 'event_espresso'),
1151
+					'target' => '',
1152
+					'class'  => $menu_class,
1153
+				),
1154
+			));
1155
+		}
1156
+		if ($this->registry->CAP->current_user_can('ee_read_events',
1157
+			'ee_admin_bar_menu_espresso-toolbar-events-today')
1158
+		) {
1159
+			//Events View Today
1160
+			$admin_bar->add_menu(array(
1161
+				'id'     => 'espresso-toolbar-events-today',
1162
+				'parent' => 'espresso-toolbar-events-view',
1163
+				'title'  => __('Today', 'event_espresso'),
1164
+				'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'default', 'status' => 'today'),
1165
+					$events_admin_url),
1166
+				'meta'   => array(
1167
+					'title'  => __('Today', 'event_espresso'),
1168
+					'target' => '',
1169
+					'class'  => $menu_class,
1170
+				),
1171
+			));
1172
+		}
1173
+		if ($this->registry->CAP->current_user_can('ee_read_events',
1174
+			'ee_admin_bar_menu_espresso-toolbar-events-month')
1175
+		) {
1176
+			//Events View This Month
1177
+			$admin_bar->add_menu(array(
1178
+				'id'     => 'espresso-toolbar-events-month',
1179
+				'parent' => 'espresso-toolbar-events-view',
1180
+				'title'  => __('This Month', 'event_espresso'),
1181
+				'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'default', 'status' => 'month'),
1182
+					$events_admin_url),
1183
+				'meta'   => array(
1184
+					'title'  => __('This Month', 'event_espresso'),
1185
+					'target' => '',
1186
+					'class'  => $menu_class,
1187
+				),
1188
+			));
1189
+		}
1190
+		//Registration Overview
1191
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1192
+			'ee_admin_bar_menu_espresso-toolbar-registrations')
1193
+		) {
1194
+			$admin_bar->add_menu(array(
1195
+				'id'     => 'espresso-toolbar-registrations',
1196
+				'parent' => 'espresso-toolbar',
1197
+				'title'  => __('Registrations', 'event_espresso'),
1198
+				'href'   => $reg_admin_url,
1199
+				'meta'   => array(
1200
+					'title'  => __('Registrations', 'event_espresso'),
1201
+					'target' => '',
1202
+					'class'  => $menu_class,
1203
+				),
1204
+			));
1205
+		}
1206
+		//Registration Overview Today
1207
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1208
+			'ee_admin_bar_menu_espresso-toolbar-registrations-today')
1209
+		) {
1210
+			$admin_bar->add_menu(array(
1211
+				'id'     => 'espresso-toolbar-registrations-today',
1212
+				'parent' => 'espresso-toolbar-registrations',
1213
+				'title'  => __('Today', 'event_espresso'),
1214
+				'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'default', 'status' => 'today'),
1215
+					$reg_admin_url),
1216
+				'meta'   => array(
1217
+					'title'  => __('Today', 'event_espresso'),
1218
+					'target' => '',
1219
+					'class'  => $menu_class,
1220
+				),
1221
+			));
1222
+		}
1223
+		//Registration Overview Today Completed
1224
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1225
+			'ee_admin_bar_menu_espresso-toolbar-registrations-today-approved')
1226
+		) {
1227
+			$admin_bar->add_menu(array(
1228
+				'id'     => 'espresso-toolbar-registrations-today-approved',
1229
+				'parent' => 'espresso-toolbar-registrations-today',
1230
+				'title'  => __('Approved', 'event_espresso'),
1231
+				'href'   => EEH_URL::add_query_args_and_nonce(array(
1232
+					'action'      => 'default',
1233
+					'status'      => 'today',
1234
+					'_reg_status' => EEM_Registration::status_id_approved,
1235
+				), $reg_admin_url),
1236
+				'meta'   => array(
1237
+					'title'  => __('Approved', 'event_espresso'),
1238
+					'target' => '',
1239
+					'class'  => $menu_class,
1240
+				),
1241
+			));
1242
+		}
1243
+		//Registration Overview Today Pending\
1244
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1245
+			'ee_admin_bar_menu_espresso-toolbar-registrations-today-pending')
1246
+		) {
1247
+			$admin_bar->add_menu(array(
1248
+				'id'     => 'espresso-toolbar-registrations-today-pending',
1249
+				'parent' => 'espresso-toolbar-registrations-today',
1250
+				'title'  => __('Pending', 'event_espresso'),
1251
+				'href'   => EEH_URL::add_query_args_and_nonce(array(
1252
+					'action'     => 'default',
1253
+					'status'     => 'today',
1254
+					'reg_status' => EEM_Registration::status_id_pending_payment,
1255
+				), $reg_admin_url),
1256
+				'meta'   => array(
1257
+					'title'  => __('Pending Payment', 'event_espresso'),
1258
+					'target' => '',
1259
+					'class'  => $menu_class,
1260
+				),
1261
+			));
1262
+		}
1263
+		//Registration Overview Today Incomplete
1264
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1265
+			'ee_admin_bar_menu_espresso-toolbar-registrations-today-not-approved')
1266
+		) {
1267
+			$admin_bar->add_menu(array(
1268
+				'id'     => 'espresso-toolbar-registrations-today-not-approved',
1269
+				'parent' => 'espresso-toolbar-registrations-today',
1270
+				'title'  => __('Not Approved', 'event_espresso'),
1271
+				'href'   => EEH_URL::add_query_args_and_nonce(array(
1272
+					'action'      => 'default',
1273
+					'status'      => 'today',
1274
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1275
+				), $reg_admin_url),
1276
+				'meta'   => array(
1277
+					'title'  => __('Not Approved', 'event_espresso'),
1278
+					'target' => '',
1279
+					'class'  => $menu_class,
1280
+				),
1281
+			));
1282
+		}
1283
+		//Registration Overview Today Incomplete
1284
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1285
+			'ee_admin_bar_menu_espresso-toolbar-registrations-today-cancelled')
1286
+		) {
1287
+			$admin_bar->add_menu(array(
1288
+				'id'     => 'espresso-toolbar-registrations-today-cancelled',
1289
+				'parent' => 'espresso-toolbar-registrations-today',
1290
+				'title'  => __('Cancelled', 'event_espresso'),
1291
+				'href'   => EEH_URL::add_query_args_and_nonce(array(
1292
+					'action'      => 'default',
1293
+					'status'      => 'today',
1294
+					'_reg_status' => EEM_Registration::status_id_cancelled,
1295
+				), $reg_admin_url),
1296
+				'meta'   => array(
1297
+					'title'  => __('Cancelled', 'event_espresso'),
1298
+					'target' => '',
1299
+					'class'  => $menu_class,
1300
+				),
1301
+			));
1302
+		}
1303
+		//Registration Overview This Month
1304
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1305
+			'ee_admin_bar_menu_espresso-toolbar-registrations-month')
1306
+		) {
1307
+			$admin_bar->add_menu(array(
1308
+				'id'     => 'espresso-toolbar-registrations-month',
1309
+				'parent' => 'espresso-toolbar-registrations',
1310
+				'title'  => __('This Month', 'event_espresso'),
1311
+				'href'   => EEH_URL::add_query_args_and_nonce(array('action' => 'default', 'status' => 'month'),
1312
+					$reg_admin_url),
1313
+				'meta'   => array(
1314
+					'title'  => __('This Month', 'event_espresso'),
1315
+					'target' => '',
1316
+					'class'  => $menu_class,
1317
+				),
1318
+			));
1319
+		}
1320
+		//Registration Overview This Month Approved
1321
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1322
+			'ee_admin_bar_menu_espresso-toolbar-registrations-month-approved')
1323
+		) {
1324
+			$admin_bar->add_menu(array(
1325
+				'id'     => 'espresso-toolbar-registrations-month-approved',
1326
+				'parent' => 'espresso-toolbar-registrations-month',
1327
+				'title'  => __('Approved', 'event_espresso'),
1328
+				'href'   => EEH_URL::add_query_args_and_nonce(array(
1329
+					'action'      => 'default',
1330
+					'status'      => 'month',
1331
+					'_reg_status' => EEM_Registration::status_id_approved,
1332
+				), $reg_admin_url),
1333
+				'meta'   => array(
1334
+					'title'  => __('Approved', 'event_espresso'),
1335
+					'target' => '',
1336
+					'class'  => $menu_class,
1337
+				),
1338
+			));
1339
+		}
1340
+		//Registration Overview This Month Pending
1341
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1342
+			'ee_admin_bar_menu_espresso-toolbar-registrations-month-pending')
1343
+		) {
1344
+			$admin_bar->add_menu(array(
1345
+				'id'     => 'espresso-toolbar-registrations-month-pending',
1346
+				'parent' => 'espresso-toolbar-registrations-month',
1347
+				'title'  => __('Pending', 'event_espresso'),
1348
+				'href'   => EEH_URL::add_query_args_and_nonce(array(
1349
+					'action'      => 'default',
1350
+					'status'      => 'month',
1351
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1352
+				), $reg_admin_url),
1353
+				'meta'   => array(
1354
+					'title'  => __('Pending', 'event_espresso'),
1355
+					'target' => '',
1356
+					'class'  => $menu_class,
1357
+				),
1358
+			));
1359
+		}
1360
+		//Registration Overview This Month Not Approved
1361
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1362
+			'ee_admin_bar_menu_espresso-toolbar-registrations-month-not-approved')
1363
+		) {
1364
+			$admin_bar->add_menu(array(
1365
+				'id'     => 'espresso-toolbar-registrations-month-not-approved',
1366
+				'parent' => 'espresso-toolbar-registrations-month',
1367
+				'title'  => __('Not Approved', 'event_espresso'),
1368
+				'href'   => EEH_URL::add_query_args_and_nonce(array(
1369
+					'action'      => 'default',
1370
+					'status'      => 'month',
1371
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1372
+				), $reg_admin_url),
1373
+				'meta'   => array(
1374
+					'title'  => __('Not Approved', 'event_espresso'),
1375
+					'target' => '',
1376
+					'class'  => $menu_class,
1377
+				),
1378
+			));
1379
+		}
1380
+		//Registration Overview This Month Cancelled
1381
+		if ($this->registry->CAP->current_user_can('ee_read_registrations',
1382
+			'ee_admin_bar_menu_espresso-toolbar-registrations-month-cancelled')
1383
+		) {
1384
+			$admin_bar->add_menu(array(
1385
+				'id'     => 'espresso-toolbar-registrations-month-cancelled',
1386
+				'parent' => 'espresso-toolbar-registrations-month',
1387
+				'title'  => __('Cancelled', 'event_espresso'),
1388
+				'href'   => EEH_URL::add_query_args_and_nonce(array(
1389
+					'action'      => 'default',
1390
+					'status'      => 'month',
1391
+					'_reg_status' => EEM_Registration::status_id_cancelled,
1392
+				), $reg_admin_url),
1393
+				'meta'   => array(
1394
+					'title'  => __('Cancelled', 'event_espresso'),
1395
+					'target' => '',
1396
+					'class'  => $menu_class,
1397
+				),
1398
+			));
1399
+		}
1400
+		//Extensions & Services
1401
+		if ($this->registry->CAP->current_user_can('ee_read_ee',
1402
+			'ee_admin_bar_menu_espresso-toolbar-extensions-and-services')
1403
+		) {
1404
+			$admin_bar->add_menu(array(
1405
+				'id'     => 'espresso-toolbar-extensions-and-services',
1406
+				'parent' => 'espresso-toolbar',
1407
+				'title'  => __('Extensions & Services', 'event_espresso'),
1408
+				'href'   => $extensions_admin_url,
1409
+				'meta'   => array(
1410
+					'title'  => __('Extensions & Services', 'event_espresso'),
1411
+					'target' => '',
1412
+					'class'  => $menu_class,
1413
+				),
1414
+			));
1415
+		}
1416
+	}
1417
+
1418
+
1419
+
1420
+	/**
1421
+	 * simply hooks into "wp_list_pages_exclude" filter (for wp_list_pages method) and makes sure EE critical pages are
1422
+	 * never returned with the function.
1423
+	 *
1424
+	 * @param  array $exclude_array any existing pages being excluded are in this array.
1425
+	 * @return array
1426
+	 */
1427
+	public function remove_pages_from_wp_list_pages($exclude_array)
1428
+	{
1429
+		return array_merge($exclude_array, $this->registry->CFG->core->get_critical_pages_array());
1430
+	}
1431 1431
 
1432 1432
 
1433 1433
 
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -186,7 +186,7 @@  discard block
 block discarded – undo
186 186
     {
187 187
         // set autoloaders for all of the classes implementing EEI_Plugin_API
188 188
         // which provide helpers for EE plugin authors to more easily register certain components with EE.
189
-        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES . 'plugin_api');
189
+        EEH_Autoloader::instance()->register_autoloaders_for_each_file_in_folder(EE_LIBRARIES.'plugin_api');
190 190
         //load and setup EE_Capabilities
191 191
         $this->registry->load_core('Capabilities');
192 192
         //caps need to be initialized on every request so that capability maps are set.
@@ -207,7 +207,7 @@  discard block
 block discarded – undo
207 207
                 && in_array($_GET['action'], array('activate', 'activate-selected'), true)
208 208
             )
209 209
         ) {
210
-            include_once EE_THIRD_PARTY . 'wp-api-basic-auth' . DS . 'basic-auth.php';
210
+            include_once EE_THIRD_PARTY.'wp-api-basic-auth'.DS.'basic-auth.php';
211 211
         }
212 212
         do_action('AHEE__EE_System__load_espresso_addons__complete');
213 213
     }
@@ -693,7 +693,7 @@  discard block
 block discarded – undo
693 693
     private function _parse_model_names()
694 694
     {
695 695
         //get all the files in the EE_MODELS folder that end in .model.php
696
-        $models = glob(EE_MODELS . '*.model.php');
696
+        $models = glob(EE_MODELS.'*.model.php');
697 697
         $model_names = array();
698 698
         $non_abstract_db_models = array();
699 699
         foreach ($models as $model) {
@@ -721,8 +721,8 @@  discard block
 block discarded – undo
721 721
      */
722 722
     private function _maybe_brew_regular()
723 723
     {
724
-        if (( ! defined('EE_DECAF') || EE_DECAF !== true) && is_readable(EE_CAFF_PATH . 'brewing_regular.php')) {
725
-            require_once EE_CAFF_PATH . 'brewing_regular.php';
724
+        if (( ! defined('EE_DECAF') || EE_DECAF !== true) && is_readable(EE_CAFF_PATH.'brewing_regular.php')) {
725
+            require_once EE_CAFF_PATH.'brewing_regular.php';
726 726
         }
727 727
     }
728 728
 
@@ -772,8 +772,8 @@  discard block
 block discarded – undo
772 772
                 'event_espresso');
773 773
             $msg .= '<ul>';
774 774
             foreach ($class_names as $class_name) {
775
-                $msg .= '<li><b>Event Espresso - ' . str_replace(array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
776
-                        $class_name) . '</b></li>';
775
+                $msg .= '<li><b>Event Espresso - '.str_replace(array('EE_', 'EEM_', 'EED_', 'EES_', 'EEW_'), '',
776
+                        $class_name).'</b></li>';
777 777
             }
778 778
             $msg .= '</ul>';
779 779
             $msg .= __('Compatibility issues can be avoided and/or resolved by keeping addons and plugins updated to the latest version.',
@@ -924,8 +924,8 @@  discard block
 block discarded – undo
924 924
         $this->registry->load_core('Session');
925 925
         do_action('AHEE__EE_System__core_loaded_and_ready');
926 926
         // load_espresso_template_tags
927
-        if (is_readable(EE_PUBLIC . 'template_tags.php')) {
928
-            require_once(EE_PUBLIC . 'template_tags.php');
927
+        if (is_readable(EE_PUBLIC.'template_tags.php')) {
928
+            require_once(EE_PUBLIC.'template_tags.php');
929 929
         }
930 930
         do_action('AHEE__EE_System__set_hooks_for_shortcodes_modules_and_addons');
931 931
         $this->registry->create('EventEspresso\core\services\assets\Registry', array(), true);
@@ -1071,7 +1071,7 @@  discard block
 block discarded – undo
1071 1071
             'href'  => $events_admin_url,
1072 1072
             'meta'  => array(
1073 1073
                 'title' => __('Event Espresso', 'event_espresso'),
1074
-                'class' => $menu_class . 'first',
1074
+                'class' => $menu_class.'first',
1075 1075
             ),
1076 1076
         ));
1077 1077
         //Events
Please login to merge, or discard this patch.
core/EE_Registry.core.php 2 patches
Indentation   +1427 added lines, -1427 removed lines patch added patch discarded remove patch
@@ -19,1463 +19,1463 @@
 block discarded – undo
19 19
 class EE_Registry implements ResettableInterface
20 20
 {
21 21
 
22
-    /**
23
-     *    EE_Registry Object
24
-     *
25
-     * @var EE_Registry $_instance
26
-     * @access    private
27
-     */
28
-    private static $_instance = null;
29
-
30
-    /**
31
-     * @var EE_Dependency_Map $_dependency_map
32
-     * @access    protected
33
-     */
34
-    protected $_dependency_map = null;
35
-
36
-    /**
37
-     * @var array $_class_abbreviations
38
-     * @access    protected
39
-     */
40
-    protected $_class_abbreviations = array();
41
-
42
-    /**
43
-     * @access public
44
-     * @var \EventEspresso\core\services\commands\CommandBusInterface $BUS
45
-     */
46
-    public $BUS;
47
-
48
-    /**
49
-     *    EE_Cart Object
50
-     *
51
-     * @access    public
52
-     * @var    EE_Cart $CART
53
-     */
54
-    public $CART = null;
55
-
56
-    /**
57
-     *    EE_Config Object
58
-     *
59
-     * @access    public
60
-     * @var    EE_Config $CFG
61
-     */
62
-    public $CFG = null;
63
-
64
-    /**
65
-     * EE_Network_Config Object
66
-     *
67
-     * @access public
68
-     * @var EE_Network_Config $NET_CFG
69
-     */
70
-    public $NET_CFG = null;
71
-
72
-    /**
73
-     *    StdClass object for storing library classes in
74
-     *
75
-     * @public LIB
76
-     * @var StdClass $LIB
77
-     */
78
-    public $LIB = null;
79
-
80
-    /**
81
-     *    EE_Request_Handler Object
82
-     *
83
-     * @access    public
84
-     * @var    EE_Request_Handler $REQ
85
-     */
86
-    public $REQ = null;
87
-
88
-    /**
89
-     *    EE_Session Object
90
-     *
91
-     * @access    public
92
-     * @var    EE_Session $SSN
93
-     */
94
-    public $SSN = null;
95
-
96
-    /**
97
-     * holds the ee capabilities object.
98
-     *
99
-     * @since 4.5.0
100
-     * @var EE_Capabilities
101
-     */
102
-    public $CAP = null;
103
-
104
-    /**
105
-     * holds the EE_Message_Resource_Manager object.
106
-     *
107
-     * @since 4.9.0
108
-     * @var EE_Message_Resource_Manager
109
-     */
110
-    public $MRM = null;
111
-
112
-
113
-    /**
114
-     * Holds the Assets Registry instance
115
-     * @var Registry
116
-     */
117
-    public $AssetsRegistry = null;
118
-
119
-    /**
120
-     *    $addons - StdClass object for holding addons which have registered themselves to work with EE core
121
-     *
122
-     * @access    public
123
-     * @var    EE_Addon[]
124
-     */
125
-    public $addons = null;
126
-
127
-    /**
128
-     *    $models
129
-     * @access    public
130
-     * @var    EEM_Base[] $models keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
131
-     */
132
-    public $models = array();
133
-
134
-    /**
135
-     *    $modules
136
-     * @access    public
137
-     * @var    EED_Module[] $modules
138
-     */
139
-    public $modules = null;
140
-
141
-    /**
142
-     *    $shortcodes
143
-     * @access    public
144
-     * @var    EES_Shortcode[] $shortcodes
145
-     */
146
-    public $shortcodes = null;
147
-
148
-    /**
149
-     *    $widgets
150
-     * @access    public
151
-     * @var    WP_Widget[] $widgets
152
-     */
153
-    public $widgets = null;
154
-
155
-    /**
156
-     * $non_abstract_db_models
157
-     * @access public
158
-     * @var array this is an array of all implemented model names (i.e. not the parent abstract models, or models
159
-     * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
160
-     * Keys are model "short names" (eg "Event") as used in model relations, and values are
161
-     * classnames (eg "EEM_Event")
162
-     */
163
-    public $non_abstract_db_models = array();
164
-
165
-
166
-    /**
167
-     *    $i18n_js_strings - internationalization for JS strings
168
-     *    usage:   EE_Registry::i18n_js_strings['string_key'] = __( 'string to translate.', 'event_espresso' );
169
-     *    in js file:  var translatedString = eei18n.string_key;
170
-     *
171
-     * @access    public
172
-     * @var    array
173
-     */
174
-    public static $i18n_js_strings = array();
175
-
176
-
177
-    /**
178
-     *    $main_file - path to espresso.php
179
-     *
180
-     * @access    public
181
-     * @var    array
182
-     */
183
-    public $main_file;
184
-
185
-    /**
186
-     * array of ReflectionClass objects where the key is the class name
187
-     *
188
-     * @access    public
189
-     * @var ReflectionClass[]
190
-     */
191
-    public $_reflectors;
192
-
193
-    /**
194
-     * boolean flag to indicate whether or not to load/save dependencies from/to the cache
195
-     *
196
-     * @access    protected
197
-     * @var boolean $_cache_on
198
-     */
199
-    protected $_cache_on = true;
200
-
201
-
202
-
203
-    /**
204
-     * @singleton method used to instantiate class object
205
-     * @access    public
206
-     * @param  \EE_Dependency_Map $dependency_map
207
-     * @return \EE_Registry instance
208
-     */
209
-    public static function instance(\EE_Dependency_Map $dependency_map = null)
210
-    {
211
-        // check if class object is instantiated
212
-        if ( ! self::$_instance instanceof EE_Registry) {
213
-            self::$_instance = new EE_Registry($dependency_map);
214
-        }
215
-        return self::$_instance;
216
-    }
217
-
218
-
219
-
220
-    /**
221
-     *protected constructor to prevent direct creation
222
-     *
223
-     * @Constructor
224
-     * @access protected
225
-     * @param  \EE_Dependency_Map $dependency_map
226
-     */
227
-    protected function __construct(\EE_Dependency_Map $dependency_map)
228
-    {
229
-        $this->_dependency_map = $dependency_map;
230
-        $this->LIB = new stdClass();
231
-        $this->addons = new stdClass();
232
-        $this->modules = new stdClass();
233
-        $this->shortcodes = new stdClass();
234
-        $this->widgets = new stdClass();
235
-        add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
236
-    }
237
-
238
-
239
-
240
-    /**
241
-     * initialize
242
-     */
243
-    public function initialize()
244
-    {
245
-        $this->_class_abbreviations = apply_filters(
246
-            'FHEE__EE_Registry____construct___class_abbreviations',
247
-            array(
248
-                'EE_Config'                                       => 'CFG',
249
-                'EE_Session'                                      => 'SSN',
250
-                'EE_Capabilities'                                 => 'CAP',
251
-                'EE_Cart'                                         => 'CART',
252
-                'EE_Network_Config'                               => 'NET_CFG',
253
-                'EE_Request_Handler'                              => 'REQ',
254
-                'EE_Message_Resource_Manager'                     => 'MRM',
255
-                'EventEspresso\core\services\commands\CommandBus' => 'BUS',
256
-                'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
257
-            )
258
-        );
259
-        $this->load_core('Base', array(), true);
260
-        // add our request and response objects to the cache
261
-        $request_loader = $this->_dependency_map->class_loader('EE_Request');
262
-        $this->_set_cached_class(
263
-            $request_loader(),
264
-            'EE_Request'
265
-        );
266
-        $response_loader = $this->_dependency_map->class_loader('EE_Response');
267
-        $this->_set_cached_class(
268
-            $response_loader(),
269
-            'EE_Response'
270
-        );
271
-        add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
272
-    }
273
-
274
-
275
-
276
-    /**
277
-     *    init
278
-     *
279
-     * @access    public
280
-     * @return    void
281
-     */
282
-    public function init()
283
-    {
284
-        // Get current page protocol
285
-        $protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
286
-        // Output admin-ajax.php URL with same protocol as current page
287
-        self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
288
-        self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
289
-    }
290
-
291
-
292
-
293
-    /**
294
-     * localize_i18n_js_strings
295
-     *
296
-     * @return string
297
-     */
298
-    public static function localize_i18n_js_strings()
299
-    {
300
-        $i18n_js_strings = (array)EE_Registry::$i18n_js_strings;
301
-        foreach ($i18n_js_strings as $key => $value) {
302
-            if (is_scalar($value)) {
303
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
304
-            }
305
-        }
306
-        return "/* <![CDATA[ */ var eei18n = " . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
307
-    }
308
-
309
-
310
-
311
-    /**
312
-     * @param mixed string | EED_Module $module
313
-     */
314
-    public function add_module($module)
315
-    {
316
-        if ($module instanceof EED_Module) {
317
-            $module_class = get_class($module);
318
-            $this->modules->{$module_class} = $module;
319
-        } else {
320
-            if ( ! class_exists('EE_Module_Request_Router')) {
321
-                $this->load_core('Module_Request_Router');
322
-            }
323
-            $this->modules->{$module} = EE_Module_Request_Router::module_factory($module);
324
-        }
325
-    }
326
-
327
-
328
-
329
-    /**
330
-     * @param string $module_name
331
-     * @return mixed EED_Module | NULL
332
-     */
333
-    public function get_module($module_name = '')
334
-    {
335
-        return isset($this->modules->{$module_name}) ? $this->modules->{$module_name} : null;
336
-    }
337
-
338
-
339
-
340
-    /**
341
-     *    loads core classes - must be singletons
342
-     *
343
-     * @access    public
344
-     * @param string $class_name - simple class name ie: session
345
-     * @param mixed  $arguments
346
-     * @param bool   $load_only
347
-     * @return mixed
348
-     */
349
-    public function load_core($class_name, $arguments = array(), $load_only = false)
350
-    {
351
-        $core_paths = apply_filters(
352
-            'FHEE__EE_Registry__load_core__core_paths',
353
-            array(
354
-                EE_CORE,
355
-                EE_ADMIN,
356
-                EE_CPTS,
357
-                EE_CORE . 'data_migration_scripts' . DS,
358
-                EE_CORE . 'request_stack' . DS,
359
-                EE_CORE . 'middleware' . DS,
360
-            )
361
-        );
362
-        // retrieve instantiated class
363
-        return $this->_load($core_paths, 'EE_', $class_name, 'core', $arguments, false, true, $load_only);
364
-    }
365
-
366
-
367
-
368
-    /**
369
-     *    loads service classes
370
-     *
371
-     * @access    public
372
-     * @param string $class_name - simple class name ie: session
373
-     * @param mixed  $arguments
374
-     * @param bool   $load_only
375
-     * @return mixed
376
-     */
377
-    public function load_service($class_name, $arguments = array(), $load_only = false)
378
-    {
379
-        $service_paths = apply_filters(
380
-            'FHEE__EE_Registry__load_service__service_paths',
381
-            array(
382
-                EE_CORE . 'services' . DS,
383
-            )
384
-        );
385
-        // retrieve instantiated class
386
-        return $this->_load($service_paths, 'EE_', $class_name, 'class', $arguments, false, true, $load_only);
387
-    }
388
-
389
-
390
-
391
-    /**
392
-     *    loads data_migration_scripts
393
-     *
394
-     * @access    public
395
-     * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
396
-     * @param mixed  $arguments
397
-     * @return EE_Data_Migration_Script_Base|mixed
398
-     */
399
-    public function load_dms($class_name, $arguments = array())
400
-    {
401
-        // retrieve instantiated class
402
-        return $this->_load(EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(), 'EE_DMS_', $class_name, 'dms', $arguments, false, false, false);
403
-    }
404
-
405
-
406
-
407
-    /**
408
-     *    loads object creating classes - must be singletons
409
-     *
410
-     * @param string $class_name - simple class name ie: attendee
411
-     * @param mixed  $arguments  - an array of arguments to pass to the class
412
-     * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to instantiate
413
-     * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then set this to FALSE (ie. when instantiating model objects from client in a loop)
414
-     * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate (default)
415
-     * @return EE_Base_Class | bool
416
-     */
417
-    public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
418
-    {
419
-        $paths = apply_filters('FHEE__EE_Registry__load_class__paths', array(
420
-            EE_CORE,
421
-            EE_CLASSES,
422
-            EE_BUSINESS,
423
-        ));
424
-        // retrieve instantiated class
425
-        return $this->_load($paths, 'EE_', $class_name, 'class', $arguments, $from_db, $cache, $load_only);
426
-    }
427
-
428
-
429
-
430
-    /**
431
-     *    loads helper classes - must be singletons
432
-     *
433
-     * @param string $class_name - simple class name ie: price
434
-     * @param mixed  $arguments
435
-     * @param bool   $load_only
436
-     * @return EEH_Base | bool
437
-     */
438
-    public function load_helper($class_name, $arguments = array(), $load_only = true)
439
-    {
440
-        // todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
441
-        $helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
442
-        // retrieve instantiated class
443
-        return $this->_load($helper_paths, 'EEH_', $class_name, 'helper', $arguments, false, true, $load_only);
444
-    }
445
-
446
-
447
-
448
-    /**
449
-     *    loads core classes - must be singletons
450
-     *
451
-     * @access    public
452
-     * @param string $class_name - simple class name ie: session
453
-     * @param mixed  $arguments
454
-     * @param bool   $load_only
455
-     * @param bool   $cache      whether to cache the object or not.
456
-     * @return mixed
457
-     */
458
-    public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
459
-    {
460
-        $paths = array(
461
-            EE_LIBRARIES,
462
-            EE_LIBRARIES . 'messages' . DS,
463
-            EE_LIBRARIES . 'shortcodes' . DS,
464
-            EE_LIBRARIES . 'qtips' . DS,
465
-            EE_LIBRARIES . 'payment_methods' . DS,
466
-        );
467
-        // retrieve instantiated class
468
-        return $this->_load($paths, 'EE_', $class_name, 'lib', $arguments, false, $cache, $load_only);
469
-    }
470
-
471
-
472
-
473
-    /**
474
-     *    loads model classes - must be singletons
475
-     *
476
-     * @param string $class_name - simple class name ie: price
477
-     * @param mixed  $arguments
478
-     * @param bool   $load_only
479
-     * @return EEM_Base | bool
480
-     */
481
-    public function load_model($class_name, $arguments = array(), $load_only = false)
482
-    {
483
-        $paths = apply_filters('FHEE__EE_Registry__load_model__paths', array(
484
-            EE_MODELS,
485
-            EE_CORE,
486
-        ));
487
-        // retrieve instantiated class
488
-        return $this->_load($paths, 'EEM_', $class_name, 'model', $arguments, false, true, $load_only);
489
-    }
490
-
491
-
492
-
493
-    /**
494
-     *    loads model classes - must be singletons
495
-     *
496
-     * @param string $class_name - simple class name ie: price
497
-     * @param mixed  $arguments
498
-     * @param bool   $load_only
499
-     * @return mixed | bool
500
-     */
501
-    public function load_model_class($class_name, $arguments = array(), $load_only = true)
502
-    {
503
-        $paths = array(
504
-            EE_MODELS . 'fields' . DS,
505
-            EE_MODELS . 'helpers' . DS,
506
-            EE_MODELS . 'relations' . DS,
507
-            EE_MODELS . 'strategies' . DS,
508
-        );
509
-        // retrieve instantiated class
510
-        return $this->_load($paths, 'EE_', $class_name, '', $arguments, false, true, $load_only);
511
-    }
512
-
513
-
514
-
515
-    /**
516
-     * Determines if $model_name is the name of an actual EE model.
517
-     *
518
-     * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
519
-     * @return boolean
520
-     */
521
-    public function is_model_name($model_name)
522
-    {
523
-        return isset($this->models[$model_name]) ? true : false;
524
-    }
525
-
526
-
527
-
528
-    /**
529
-     *    generic class loader
530
-     *
531
-     * @param string $path_to_file - directory path to file location, not including filename
532
-     * @param string $file_name    - file name  ie:  my_file.php, including extension
533
-     * @param string $type         - file type - core? class? helper? model?
534
-     * @param mixed  $arguments
535
-     * @param bool   $load_only
536
-     * @return mixed
537
-     */
538
-    public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
539
-    {
540
-        // retrieve instantiated class
541
-        return $this->_load($path_to_file, '', $file_name, $type, $arguments, false, true, $load_only);
542
-    }
543
-
544
-
545
-
546
-    /**
547
-     *    load_addon
548
-     *
549
-     * @param string $path_to_file - directory path to file location, not including filename
550
-     * @param string $class_name   - full class name  ie:  My_Class
551
-     * @param string $type         - file type - core? class? helper? model?
552
-     * @param mixed  $arguments
553
-     * @param bool   $load_only
554
-     * @return EE_Addon
555
-     */
556
-    public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
557
-    {
558
-        // retrieve instantiated class
559
-        return $this->_load($path_to_file, 'addon', $class_name, $type, $arguments, false, true, $load_only);
560
-    }
561
-
562
-
563
-
564
-    /**
565
-     * instantiates, caches, and automatically resolves dependencies
566
-     * for classes that use a Fully Qualified Class Name.
567
-     * if the class is not capable of being loaded using PSR-4 autoloading,
568
-     * then you need to use one of the existing load_*() methods
569
-     * which can resolve the classname and filepath from the passed arguments
570
-     *
571
-     * @param bool|string $class_name   Fully Qualified Class Name
572
-     * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
573
-     * @param bool        $cache        whether to cache the instantiated object for reuse
574
-     * @param bool        $from_db      some classes are instantiated from the db
575
-     *                                  and thus call a different method to instantiate
576
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
577
-     * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
578
-     * @return mixed                    null = failure to load or instantiate class object.
579
-     *                                  object = class loaded and instantiated successfully.
580
-     *                                  bool = fail or success when $load_only is true
581
-     */
582
-    public function create(
583
-        $class_name = false,
584
-        $arguments = array(),
585
-        $cache = false,
586
-        $from_db = false,
587
-        $load_only = false,
588
-        $addon = false
589
-    ) {
590
-        $class_name = ltrim($class_name, '\\');
591
-        $class_name = $this->_dependency_map->get_alias($class_name);
592
-        if ( ! class_exists($class_name)) {
593
-            // maybe the class is registered with a preceding \
594
-            $class_name = strpos($class_name, '\\') !== 0 ? '\\' . $class_name : $class_name;
595
-            // still doesn't exist ?
596
-            if ( ! class_exists($class_name)) {
597
-                return null;
598
-            }
599
-        }
600
-        // if we're only loading the class and it already exists, then let's just return true immediately
601
-        if ($load_only) {
602
-            return true;
603
-        }
604
-        $addon = $addon ? 'addon' : '';
605
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
606
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
607
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
608
-        if ($this->_cache_on && $cache && ! $load_only) {
609
-            // return object if it's already cached
610
-            $cached_class = $this->_get_cached_class($class_name, $addon);
611
-            if ($cached_class !== null) {
612
-                return $cached_class;
613
-            }
614
-        }
615
-        // instantiate the requested object
616
-        $class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
617
-        if ($this->_cache_on && $cache) {
618
-            // save it for later... kinda like gum  { : $
619
-            $this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
620
-        }
621
-        $this->_cache_on = true;
622
-        return $class_obj;
623
-    }
624
-
625
-
626
-
627
-    /**
628
-     * instantiates, caches, and injects dependencies for classes
629
-     *
630
-     * @param array       $file_paths   an array of paths to folders to look in
631
-     * @param string      $class_prefix EE  or EEM or... ???
632
-     * @param bool|string $class_name   $class name
633
-     * @param string      $type         file type - core? class? helper? model?
634
-     * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
635
-     * @param bool        $from_db      some classes are instantiated from the db
636
-     *                                  and thus call a different method to instantiate
637
-     * @param bool        $cache        whether to cache the instantiated object for reuse
638
-     * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
639
-     * @return null|object|bool         null = failure to load or instantiate class object.
640
-     *                                  object = class loaded and instantiated successfully.
641
-     *                                  bool = fail or success when $load_only is true
642
-     */
643
-    protected function _load(
644
-        $file_paths = array(),
645
-        $class_prefix = 'EE_',
646
-        $class_name = false,
647
-        $type = 'class',
648
-        $arguments = array(),
649
-        $from_db = false,
650
-        $cache = true,
651
-        $load_only = false
652
-    ) {
653
-        $class_name = ltrim($class_name, '\\');
654
-        // strip php file extension
655
-        $class_name = str_replace('.php', '', trim($class_name));
656
-        // does the class have a prefix ?
657
-        if ( ! empty($class_prefix) && $class_prefix != 'addon') {
658
-            // make sure $class_prefix is uppercase
659
-            $class_prefix = strtoupper(trim($class_prefix));
660
-            // add class prefix ONCE!!!
661
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
662
-        }
663
-        $class_name = $this->_dependency_map->get_alias($class_name);
664
-        $class_exists = class_exists($class_name);
665
-        // if we're only loading the class and it already exists, then let's just return true immediately
666
-        if ($load_only && $class_exists) {
667
-            return true;
668
-        }
669
-        // $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
670
-        // $cache is controlled by individual calls to separate Registry loader methods like load_class()
671
-        // $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
672
-        if ($this->_cache_on && $cache && ! $load_only) {
673
-            // return object if it's already cached
674
-            $cached_class = $this->_get_cached_class($class_name, $class_prefix);
675
-            if ($cached_class !== null) {
676
-                return $cached_class;
677
-            }
678
-        }
679
-        // if the class doesn't already exist.. then we need to try and find the file and load it
680
-        if ( ! $class_exists) {
681
-            // get full path to file
682
-            $path = $this->_resolve_path($class_name, $type, $file_paths);
683
-            // load the file
684
-            $loaded = $this->_require_file($path, $class_name, $type, $file_paths);
685
-            // if loading failed, or we are only loading a file but NOT instantiating an object
686
-            if ( ! $loaded || $load_only) {
687
-                // return boolean if only loading, or null if an object was expected
688
-                return $load_only ? $loaded : null;
689
-            }
690
-        }
691
-        // instantiate the requested object
692
-        $class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
693
-        if ($this->_cache_on && $cache) {
694
-            // save it for later... kinda like gum  { : $
695
-            $this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
696
-        }
697
-        $this->_cache_on = true;
698
-        return $class_obj;
699
-    }
700
-
701
-
702
-
703
-
704
-    /**
705
-     * _get_cached_class
706
-     * attempts to find a cached version of the requested class
707
-     * by looking in the following places:
708
-     *        $this->{$class_abbreviation}            ie:    $this->CART
709
-     *        $this->{$class_name}                        ie:    $this->Some_Class
710
-     *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
711
-     *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
712
-     *
713
-     * @access protected
714
-     * @param string $class_name
715
-     * @param string $class_prefix
716
-     * @return mixed
717
-     */
718
-    protected function _get_cached_class($class_name, $class_prefix = '')
719
-    {
720
-        if ($class_name === 'EE_Registry') {
721
-            return $this;
722
-        }
723
-        // have to specify something, but not anything that will conflict
724
-        $class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
725
-            ? $this->_class_abbreviations[ $class_name ]
726
-            : 'FANCY_BATMAN_PANTS';
727
-        $class_name = str_replace('\\', '_', $class_name);
728
-        // check if class has already been loaded, and return it if it has been
729
-        if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
730
-            return $this->{$class_abbreviation};
731
-        }
732
-        if (isset ($this->{$class_name})) {
733
-            return $this->{$class_name};
734
-        }
735
-        if (isset ($this->LIB->{$class_name})) {
736
-            return $this->LIB->{$class_name};
737
-        }
738
-        if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
739
-            return $this->addons->{$class_name};
740
-        }
741
-        return null;
742
-    }
743
-
744
-
745
-
746
-    /**
747
-     * removes a cached version of the requested class
748
-     *
749
-     * @param string $class_name
750
-     * @param boolean $addon
751
-     * @return boolean
752
-     */
753
-    public function clear_cached_class($class_name, $addon = false)
754
-    {
755
-        // have to specify something, but not anything that will conflict
756
-        $class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
757
-            ? $this->_class_abbreviations[ $class_name ]
758
-            : 'FANCY_BATMAN_PANTS';
759
-        $class_name = str_replace('\\', '_', $class_name);
760
-        // check if class has already been loaded, and return it if it has been
761
-        if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
762
-            $this->{$class_abbreviation} = null;
763
-            return true;
764
-        }
765
-        if (isset($this->{$class_name})) {
766
-            $this->{$class_name} = null;
767
-            return true;
768
-        }
769
-        if (isset($this->LIB->{$class_name})) {
770
-            unset($this->LIB->{$class_name});
771
-            return true;
772
-        }
773
-        if ($addon && isset($this->addons->{$class_name})) {
774
-            unset($this->addons->{$class_name});
775
-            return true;
776
-        }
777
-        return false;
778
-    }
779
-
780
-
781
-    /**
782
-     * _resolve_path
783
-     * attempts to find a full valid filepath for the requested class.
784
-     * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
785
-     * then returns that path if the target file has been found and is readable
786
-     *
787
-     * @access protected
788
-     * @param string $class_name
789
-     * @param string $type
790
-     * @param array  $file_paths
791
-     * @return string | bool
792
-     */
793
-    protected function _resolve_path($class_name, $type = '', $file_paths = array())
794
-    {
795
-        // make sure $file_paths is an array
796
-        $file_paths = is_array($file_paths) ? $file_paths : array($file_paths);
797
-        // cycle thru paths
798
-        foreach ($file_paths as $key => $file_path) {
799
-            // convert all separators to proper DS, if no filepath, then use EE_CLASSES
800
-            $file_path = $file_path ? str_replace(array('/', '\\'), DS, $file_path) : EE_CLASSES;
801
-            // prep file type
802
-            $type = ! empty($type) ? trim($type, '.') . '.' : '';
803
-            // build full file path
804
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
805
-            //does the file exist and can be read ?
806
-            if (is_readable($file_paths[$key])) {
807
-                return $file_paths[$key];
808
-            }
809
-        }
810
-        return false;
811
-    }
812
-
813
-
814
-
815
-    /**
816
-     * _require_file
817
-     * basically just performs a require_once()
818
-     * but with some error handling
819
-     *
820
-     * @access protected
821
-     * @param  string $path
822
-     * @param  string $class_name
823
-     * @param  string $type
824
-     * @param  array  $file_paths
825
-     * @return boolean
826
-     * @throws \EE_Error
827
-     */
828
-    protected function _require_file($path, $class_name, $type = '', $file_paths = array())
829
-    {
830
-        // don't give up! you gotta...
831
-        try {
832
-            //does the file exist and can it be read ?
833
-            if ( ! $path) {
834
-                // so sorry, can't find the file
835
-                throw new EE_Error (
836
-                    sprintf(
837
-                        __('The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s', 'event_espresso'),
838
-                        trim($type, '.'),
839
-                        $class_name,
840
-                        '<br />' . implode(',<br />', $file_paths)
841
-                    )
842
-                );
843
-            }
844
-            // get the file
845
-            require_once($path);
846
-            // if the class isn't already declared somewhere
847
-            if (class_exists($class_name, false) === false) {
848
-                // so sorry, not a class
849
-                throw new EE_Error(
850
-                    sprintf(
851
-                        __('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
852
-                        $type,
853
-                        $path,
854
-                        $class_name
855
-                    )
856
-                );
857
-            }
858
-        } catch (EE_Error $e) {
859
-            $e->get_error();
860
-            return false;
861
-        }
862
-        return true;
863
-    }
864
-
865
-
866
-
867
-    /**
868
-     * _create_object
869
-     * Attempts to instantiate the requested class via any of the
870
-     * commonly used instantiation methods employed throughout EE.
871
-     * The priority for instantiation is as follows:
872
-     *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
873
-     *        - model objects via their 'new_instance_from_db' method
874
-     *        - model objects via their 'new_instance' method
875
-     *        - "singleton" classes" via their 'instance' method
876
-     *    - standard instantiable classes via their __constructor
877
-     * Prior to instantiation, if the classname exists in the dependency_map,
878
-     * then the constructor for the requested class will be examined to determine
879
-     * if any dependencies exist, and if they can be injected.
880
-     * If so, then those classes will be added to the array of arguments passed to the constructor
881
-     *
882
-     * @access protected
883
-     * @param string $class_name
884
-     * @param array  $arguments
885
-     * @param string $type
886
-     * @param bool   $from_db
887
-     * @return null | object
888
-     * @throws \EE_Error
889
-     */
890
-    protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
891
-    {
892
-        $class_obj = null;
893
-        $instantiation_mode = '0) none';
894
-        // don't give up! you gotta...
895
-        try {
896
-            // create reflection
897
-            $reflector = $this->get_ReflectionClass($class_name);
898
-            // make sure arguments are an array
899
-            $arguments = is_array($arguments) ? $arguments : array($arguments);
900
-            // and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
901
-            // else wrap it in an additional array so that it doesn't get split into multiple parameters
902
-            $arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
903
-                ? $arguments
904
-                : array($arguments);
905
-            // attempt to inject dependencies ?
906
-            if ($this->_dependency_map->has($class_name)) {
907
-                $arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
908
-            }
909
-            // instantiate the class if possible
910
-            if ($reflector->isAbstract()) {
911
-                // nothing to instantiate, loading file was enough
912
-                // does not throw an exception so $instantiation_mode is unused
913
-                // $instantiation_mode = "1) no constructor abstract class";
914
-                $class_obj = true;
915
-            } else if ($reflector->getConstructor() === null && $reflector->isInstantiable() && empty($arguments)) {
916
-                // no constructor = static methods only... nothing to instantiate, loading file was enough
917
-                $instantiation_mode = "2) no constructor but instantiable";
918
-                $class_obj = $reflector->newInstance();
919
-            } else if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
920
-                $instantiation_mode = "3) new_instance_from_db()";
921
-                $class_obj = call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
922
-            } else if (method_exists($class_name, 'new_instance')) {
923
-                $instantiation_mode = "4) new_instance()";
924
-                $class_obj = call_user_func_array(array($class_name, 'new_instance'), $arguments);
925
-            } else if (method_exists($class_name, 'instance')) {
926
-                $instantiation_mode = "5) instance()";
927
-                $class_obj = call_user_func_array(array($class_name, 'instance'), $arguments);
928
-            } else if ($reflector->isInstantiable()) {
929
-                $instantiation_mode = "6) constructor";
930
-                $class_obj = $reflector->newInstanceArgs($arguments);
931
-            } else {
932
-                // heh ? something's not right !
933
-                throw new EE_Error(
934
-                    sprintf(
935
-                        __('The %s file %s could not be instantiated.', 'event_espresso'),
936
-                        $type,
937
-                        $class_name
938
-                    )
939
-                );
940
-            }
941
-        } catch (Exception $e) {
942
-            if ( ! $e instanceof EE_Error) {
943
-                $e = new EE_Error(
944
-                    sprintf(
945
-                        __('The following error occurred while attempting to instantiate "%1$s": %2$s %3$s %2$s instantiation mode : %4$s', 'event_espresso'),
946
-                        $class_name,
947
-                        '<br />',
948
-                        $e->getMessage(),
949
-                        $instantiation_mode
950
-                    )
951
-                );
952
-            }
953
-            $e->get_error();
954
-        }
955
-        return $class_obj;
956
-    }
957
-
958
-
959
-
960
-    /**
961
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
962
-     * @param array $array
963
-     * @return bool
964
-     */
965
-    protected function _array_is_numerically_and_sequentially_indexed(array $array)
966
-    {
967
-        return ! empty($array) ? array_keys($array) === range(0, count($array) - 1) : true;
968
-    }
969
-
970
-
971
-
972
-    /**
973
-     * getReflectionClass
974
-     * checks if a ReflectionClass object has already been generated for a class
975
-     * and returns that instead of creating a new one
976
-     *
977
-     * @access public
978
-     * @param string $class_name
979
-     * @return ReflectionClass
980
-     */
981
-    public function get_ReflectionClass($class_name)
982
-    {
983
-        if (
984
-            ! isset($this->_reflectors[$class_name])
985
-            || ! $this->_reflectors[$class_name] instanceof ReflectionClass
986
-        ) {
987
-            $this->_reflectors[$class_name] = new ReflectionClass($class_name);
988
-        }
989
-        return $this->_reflectors[$class_name];
990
-    }
991
-
992
-
993
-
994
-    /**
995
-     * _resolve_dependencies
996
-     * examines the constructor for the requested class to determine
997
-     * if any dependencies exist, and if they can be injected.
998
-     * If so, then those classes will be added to the array of arguments passed to the constructor
999
-     * PLZ NOTE: this is achieved by type hinting the constructor params
1000
-     * For example:
1001
-     *        if attempting to load a class "Foo" with the following constructor:
1002
-     *        __construct( Bar $bar_class, Fighter $grohl_class )
1003
-     *        then $bar_class and $grohl_class will be added to the $arguments array,
1004
-     *        but only IF they are NOT already present in the incoming arguments array,
1005
-     *        and the correct classes can be loaded
1006
-     *
1007
-     * @access protected
1008
-     * @param ReflectionClass $reflector
1009
-     * @param string          $class_name
1010
-     * @param array           $arguments
1011
-     * @return array
1012
-     * @throws \ReflectionException
1013
-     */
1014
-    protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1015
-    {
1016
-        // let's examine the constructor
1017
-        $constructor = $reflector->getConstructor();
1018
-        // whu? huh? nothing?
1019
-        if ( ! $constructor) {
1020
-            return $arguments;
1021
-        }
1022
-        // get constructor parameters
1023
-        $params = $constructor->getParameters();
1024
-        // and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1025
-        $argument_keys = array_keys($arguments);
1026
-        // now loop thru all of the constructors expected parameters
1027
-        foreach ($params as $index => $param) {
1028
-            // is this a dependency for a specific class ?
1029
-            $param_class = $param->getClass() ? $param->getClass()->name : null;
1030
-            // BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1031
-            $param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1032
-                ? $this->_dependency_map->get_alias($param_class, $class_name)
1033
-                : $param_class;
1034
-            if (
1035
-                // param is not even a class
1036
-                empty($param_class)
1037
-                // and something already exists in the incoming arguments for this param
1038
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1039
-            ) {
1040
-                // so let's skip this argument and move on to the next
1041
-                continue;
1042
-            }
1043
-            if (
1044
-                // parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1045
-                ! empty($param_class)
1046
-                && isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1047
-                && $arguments[$argument_keys[$index]] instanceof $param_class
1048
-            ) {
1049
-                // skip this argument and move on to the next
1050
-                continue;
1051
-            }
1052
-            if (
1053
-                // parameter is type hinted as a class, and should be injected
1054
-                ! empty($param_class)
1055
-                && $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1056
-            ) {
1057
-                $arguments = $this->_resolve_dependency($class_name, $param_class, $arguments, $index);
1058
-            } else {
1059
-                try {
1060
-                    $arguments[$index] = $param->getDefaultValue();
1061
-                } catch (ReflectionException $e) {
1062
-                    throw new ReflectionException(
1063
-                        sprintf(
1064
-                            __('%1$s for parameter "$%2$s"', 'event_espresso'),
1065
-                            $e->getMessage(),
1066
-                            $param->getName()
1067
-                        )
1068
-                    );
1069
-                }
1070
-            }
1071
-        }
1072
-        return $arguments;
1073
-    }
1074
-
1075
-
1076
-
1077
-    /**
1078
-     * @access protected
1079
-     * @param string $class_name
1080
-     * @param string $param_class
1081
-     * @param array  $arguments
1082
-     * @param mixed  $index
1083
-     * @return array
1084
-     */
1085
-    protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1086
-    {
1087
-        $dependency = null;
1088
-        // should dependency be loaded from cache ?
1089
-        $cache_on = $this->_dependency_map->loading_strategy_for_class_dependency($class_name, $param_class)
1090
-                    !== EE_Dependency_Map::load_new_object
1091
-            ? true
1092
-            : false;
1093
-        // we might have a dependency...
1094
-        // let's MAYBE try and find it in our cache if that's what's been requested
1095
-        $cached_class = $cache_on ? $this->_get_cached_class($param_class) : null;
1096
-        // and grab it if it exists
1097
-        if ($cached_class instanceof $param_class) {
1098
-            $dependency = $cached_class;
1099
-        } else if ($param_class !== $class_name) {
1100
-            // obtain the loader method from the dependency map
1101
-            $loader = $this->_dependency_map->class_loader($param_class);
1102
-            // is loader a custom closure ?
1103
-            if ($loader instanceof Closure) {
1104
-                $dependency = $loader();
1105
-            } else {
1106
-                // set the cache on property for the recursive loading call
1107
-                $this->_cache_on = $cache_on;
1108
-                // if not, then let's try and load it via the registry
1109
-                if ($loader && method_exists($this, $loader)) {
1110
-                    $dependency = $this->{$loader}($param_class);
1111
-                } else {
1112
-                    $dependency = $this->create($param_class, array(), $cache_on);
1113
-                }
1114
-            }
1115
-        }
1116
-        // did we successfully find the correct dependency ?
1117
-        if ($dependency instanceof $param_class) {
1118
-            // then let's inject it into the incoming array of arguments at the correct location
1119
-            if (isset($argument_keys[$index])) {
1120
-                $arguments[$argument_keys[$index]] = $dependency;
1121
-            } else {
1122
-                $arguments[$index] = $dependency;
1123
-            }
1124
-        }
1125
-        return $arguments;
1126
-    }
1127
-
1128
-
1129
-
1130
-    /**
1131
-     * _set_cached_class
1132
-     * attempts to cache the instantiated class locally
1133
-     * in one of the following places, in the following order:
1134
-     *        $this->{class_abbreviation}   ie:    $this->CART
1135
-     *        $this->{$class_name}          ie:    $this->Some_Class
1136
-     *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1137
-     *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1138
-     *
1139
-     * @access protected
1140
-     * @param object $class_obj
1141
-     * @param string $class_name
1142
-     * @param string $class_prefix
1143
-     * @param bool   $from_db
1144
-     * @return void
1145
-     */
1146
-    protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1147
-    {
1148
-        if ($class_name === 'EE_Registry' || empty($class_obj)) {
1149
-            return;
1150
-        }
1151
-        // return newly instantiated class
1152
-        if (isset($this->_class_abbreviations[$class_name])) {
1153
-            $class_abbreviation = $this->_class_abbreviations[$class_name];
1154
-            $this->{$class_abbreviation} = $class_obj;
1155
-            return;
1156
-        }
1157
-        $class_name = str_replace('\\', '_', $class_name);
1158
-        if (property_exists($this, $class_name)) {
1159
-            $this->{$class_name} = $class_obj;
1160
-            return;
1161
-        }
1162
-        if ($class_prefix === 'addon') {
1163
-            $this->addons->{$class_name} = $class_obj;
1164
-            return;
1165
-        }
1166
-        if ( ! $from_db) {
1167
-            $this->LIB->{$class_name} = $class_obj;
1168
-        }
1169
-    }
1170
-
1171
-
1172
-
1173
-    /**
1174
-     * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1175
-     *
1176
-     * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1177
-     *                          in the EE_Dependency_Map::$_class_loaders array,
1178
-     *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1179
-     * @param array  $arguments
1180
-     * @return object
1181
-     */
1182
-    public static function factory($classname, $arguments = array())
1183
-    {
1184
-        $loader = self::instance()->_dependency_map->class_loader($classname);
1185
-        if ($loader instanceof Closure) {
1186
-            return $loader($arguments);
1187
-        }
1188
-        if (method_exists(EE_Registry::instance(), $loader)) {
1189
-            return EE_Registry::instance()->{$loader}($classname, $arguments);
1190
-        }
1191
-        return null;
1192
-    }
1193
-
1194
-
1195
-
1196
-    /**
1197
-     * Gets the addon by its name/slug (not classname. For that, just
1198
-     * use the classname as the property name on EE_Config::instance()->addons)
1199
-     *
1200
-     * @param string $name
1201
-     * @return EE_Addon
1202
-     */
1203
-    public function get_addon_by_name($name)
1204
-    {
1205
-        foreach ($this->addons as $addon) {
1206
-            if ($addon->name() == $name) {
1207
-                return $addon;
1208
-            }
1209
-        }
1210
-        return null;
1211
-    }
1212
-
1213
-
1214
-
1215
-    /**
1216
-     * Gets an array of all the registered addons, where the keys are their names. (ie, what each returns for their name() function) They're already available on EE_Config::instance()->addons as properties, where each property's name is
1217
-     * the addon's classname. So if you just want to get the addon by classname, use EE_Config::instance()->addons->{classname}
1218
-     *
1219
-     * @return EE_Addon[] where the KEYS are the addon's name()
1220
-     */
1221
-    public function get_addons_by_name()
1222
-    {
1223
-        $addons = array();
1224
-        foreach ($this->addons as $addon) {
1225
-            $addons[$addon->name()] = $addon;
1226
-        }
1227
-        return $addons;
1228
-    }
1229
-
1230
-
1231
-
1232
-    /**
1233
-     * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1234
-     * a stale copy of it around
1235
-     *
1236
-     * @param string $model_name
1237
-     * @return \EEM_Base
1238
-     * @throws \EE_Error
1239
-     */
1240
-    public function reset_model($model_name)
1241
-    {
1242
-        $model_class_name = strpos($model_name, 'EEM_') !== 0 ? "EEM_{$model_name}" : $model_name;
1243
-        if ( ! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1244
-            return null;
1245
-        }
1246
-        //get that model reset it and make sure we nuke the old reference to it
1247
-        if ($this->LIB->{$model_class_name} instanceof $model_class_name && is_callable(array($model_class_name, 'reset'))) {
1248
-            $this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1249
-        } else {
1250
-            throw new EE_Error(sprintf(__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1251
-        }
1252
-        return $this->LIB->{$model_class_name};
1253
-    }
1254
-
1255
-
1256
-
1257
-    /**
1258
-     * Resets the registry.
1259
-     * The criteria for what gets reset is based on what can be shared between sites on the same request when switch_to_blog
1260
-     * is used in a multisite install.  Here is a list of things that are NOT reset.
1261
-     * - $_dependency_map
1262
-     * - $_class_abbreviations
1263
-     * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1264
-     * - $REQ:  Still on the same request so no need to change.
1265
-     * - $CAP: There is no site specific state in the EE_Capability class.
1266
-     * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only one Session
1267
-     *         can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1268
-     * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1269
-     *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1270
-     *             switch or on the restore.
1271
-     * - $modules
1272
-     * - $shortcodes
1273
-     * - $widgets
1274
-     *
1275
-     * @param boolean $hard             whether to reset data in the database too, or just refresh
1276
-     *                                  the Registry to its state at the beginning of the request
1277
-     * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1278
-     *                                  or just reset without re-instantiating (handy to set to FALSE if you're not sure if you CAN
1279
-     *                                  currently reinstantiate the singletons at the moment)
1280
-     * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so client
1281
-     *                                  code instead can just change the model context to a different blog id if necessary
1282
-     * @return EE_Registry
1283
-     */
1284
-    public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1285
-    {
1286
-        $instance = self::instance();
1287
-        $instance->_cache_on = true;
1288
-        // reset some "special" classes
1289
-        EEH_Activation::reset();
1290
-        $instance->CFG = $instance->CFG->reset($hard, $reinstantiate);
1291
-        $instance->CART = null;
1292
-        $instance->MRM = null;
1293
-        $instance->AssetsRegistry = null;
1294
-        $instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1295
-        //messages reset
1296
-        EED_Messages::reset();
1297
-        //handle of objects cached on LIB
1298
-        foreach (array('LIB', 'modules', 'shortcodes') as $cache) {
1299
-            foreach ($instance->{$cache} as $class_name => $class) {
1300
-                if (EE_Registry::_reset_and_unset_object($class, $reset_models)) {
1301
-                    unset($instance->{$cache}->{$class_name});
1302
-                }
1303
-            }
1304
-        }
1305
-        return $instance;
1306
-    }
1307
-
1308
-
1309
-
1310
-    /**
1311
-     * if passed object implements ResettableInterface, then call it's reset() method
1312
-     * if passed object implements InterminableInterface, then return false,
1313
-     * to indicate that it should NOT be cleared from the Registry cache
1314
-     *
1315
-     * @param      $object
1316
-     * @param bool $reset_models
1317
-     * @return bool returns true if cached object should be unset
1318
-     */
1319
-    private static function _reset_and_unset_object($object, $reset_models)
1320
-    {
1321
-        static $count = 0;
1322
-        $count++;
1323
-        if ($object instanceof ResettableInterface) {
1324
-            if ($object instanceof EEM_Base) {
1325
-                if ($reset_models) {
1326
-                    $object->reset();
1327
-                    return true;
1328
-                }
1329
-                return false;
1330
-            }
1331
-            $object->reset();
1332
-            return true;
1333
-        }
1334
-        if ( ! $object instanceof InterminableInterface) {
1335
-            return true;
1336
-        }
1337
-        return false;
1338
-    }
1339
-
1340
-
1341
-
1342
-    /**
1343
-     * @override magic methods
1344
-     * @return void
1345
-     */
1346
-    public final function __destruct()
1347
-    {
1348
-    }
1349
-
1350
-
1351
-
1352
-    /**
1353
-     * @param $a
1354
-     * @param $b
1355
-     */
1356
-    public final function __call($a, $b)
1357
-    {
1358
-    }
1359
-
1360
-
1361
-
1362
-    /**
1363
-     * @param $a
1364
-     */
1365
-    public final function __get($a)
1366
-    {
1367
-    }
1368
-
1369
-
1370
-
1371
-    /**
1372
-     * @param $a
1373
-     * @param $b
1374
-     */
1375
-    public final function __set($a, $b)
1376
-    {
1377
-    }
1378
-
1379
-
1380
-
1381
-    /**
1382
-     * @param $a
1383
-     */
1384
-    public final function __isset($a)
1385
-    {
1386
-    }
22
+	/**
23
+	 *    EE_Registry Object
24
+	 *
25
+	 * @var EE_Registry $_instance
26
+	 * @access    private
27
+	 */
28
+	private static $_instance = null;
29
+
30
+	/**
31
+	 * @var EE_Dependency_Map $_dependency_map
32
+	 * @access    protected
33
+	 */
34
+	protected $_dependency_map = null;
35
+
36
+	/**
37
+	 * @var array $_class_abbreviations
38
+	 * @access    protected
39
+	 */
40
+	protected $_class_abbreviations = array();
41
+
42
+	/**
43
+	 * @access public
44
+	 * @var \EventEspresso\core\services\commands\CommandBusInterface $BUS
45
+	 */
46
+	public $BUS;
47
+
48
+	/**
49
+	 *    EE_Cart Object
50
+	 *
51
+	 * @access    public
52
+	 * @var    EE_Cart $CART
53
+	 */
54
+	public $CART = null;
55
+
56
+	/**
57
+	 *    EE_Config Object
58
+	 *
59
+	 * @access    public
60
+	 * @var    EE_Config $CFG
61
+	 */
62
+	public $CFG = null;
63
+
64
+	/**
65
+	 * EE_Network_Config Object
66
+	 *
67
+	 * @access public
68
+	 * @var EE_Network_Config $NET_CFG
69
+	 */
70
+	public $NET_CFG = null;
71
+
72
+	/**
73
+	 *    StdClass object for storing library classes in
74
+	 *
75
+	 * @public LIB
76
+	 * @var StdClass $LIB
77
+	 */
78
+	public $LIB = null;
79
+
80
+	/**
81
+	 *    EE_Request_Handler Object
82
+	 *
83
+	 * @access    public
84
+	 * @var    EE_Request_Handler $REQ
85
+	 */
86
+	public $REQ = null;
87
+
88
+	/**
89
+	 *    EE_Session Object
90
+	 *
91
+	 * @access    public
92
+	 * @var    EE_Session $SSN
93
+	 */
94
+	public $SSN = null;
95
+
96
+	/**
97
+	 * holds the ee capabilities object.
98
+	 *
99
+	 * @since 4.5.0
100
+	 * @var EE_Capabilities
101
+	 */
102
+	public $CAP = null;
103
+
104
+	/**
105
+	 * holds the EE_Message_Resource_Manager object.
106
+	 *
107
+	 * @since 4.9.0
108
+	 * @var EE_Message_Resource_Manager
109
+	 */
110
+	public $MRM = null;
111
+
112
+
113
+	/**
114
+	 * Holds the Assets Registry instance
115
+	 * @var Registry
116
+	 */
117
+	public $AssetsRegistry = null;
118
+
119
+	/**
120
+	 *    $addons - StdClass object for holding addons which have registered themselves to work with EE core
121
+	 *
122
+	 * @access    public
123
+	 * @var    EE_Addon[]
124
+	 */
125
+	public $addons = null;
126
+
127
+	/**
128
+	 *    $models
129
+	 * @access    public
130
+	 * @var    EEM_Base[] $models keys are 'short names' (eg Event), values are class names (eg 'EEM_Event')
131
+	 */
132
+	public $models = array();
133
+
134
+	/**
135
+	 *    $modules
136
+	 * @access    public
137
+	 * @var    EED_Module[] $modules
138
+	 */
139
+	public $modules = null;
140
+
141
+	/**
142
+	 *    $shortcodes
143
+	 * @access    public
144
+	 * @var    EES_Shortcode[] $shortcodes
145
+	 */
146
+	public $shortcodes = null;
147
+
148
+	/**
149
+	 *    $widgets
150
+	 * @access    public
151
+	 * @var    WP_Widget[] $widgets
152
+	 */
153
+	public $widgets = null;
154
+
155
+	/**
156
+	 * $non_abstract_db_models
157
+	 * @access public
158
+	 * @var array this is an array of all implemented model names (i.e. not the parent abstract models, or models
159
+	 * which don't actually fetch items from the DB in the normal way (ie, are not children of EEM_Base)).
160
+	 * Keys are model "short names" (eg "Event") as used in model relations, and values are
161
+	 * classnames (eg "EEM_Event")
162
+	 */
163
+	public $non_abstract_db_models = array();
164
+
165
+
166
+	/**
167
+	 *    $i18n_js_strings - internationalization for JS strings
168
+	 *    usage:   EE_Registry::i18n_js_strings['string_key'] = __( 'string to translate.', 'event_espresso' );
169
+	 *    in js file:  var translatedString = eei18n.string_key;
170
+	 *
171
+	 * @access    public
172
+	 * @var    array
173
+	 */
174
+	public static $i18n_js_strings = array();
175
+
176
+
177
+	/**
178
+	 *    $main_file - path to espresso.php
179
+	 *
180
+	 * @access    public
181
+	 * @var    array
182
+	 */
183
+	public $main_file;
184
+
185
+	/**
186
+	 * array of ReflectionClass objects where the key is the class name
187
+	 *
188
+	 * @access    public
189
+	 * @var ReflectionClass[]
190
+	 */
191
+	public $_reflectors;
192
+
193
+	/**
194
+	 * boolean flag to indicate whether or not to load/save dependencies from/to the cache
195
+	 *
196
+	 * @access    protected
197
+	 * @var boolean $_cache_on
198
+	 */
199
+	protected $_cache_on = true;
200
+
201
+
202
+
203
+	/**
204
+	 * @singleton method used to instantiate class object
205
+	 * @access    public
206
+	 * @param  \EE_Dependency_Map $dependency_map
207
+	 * @return \EE_Registry instance
208
+	 */
209
+	public static function instance(\EE_Dependency_Map $dependency_map = null)
210
+	{
211
+		// check if class object is instantiated
212
+		if ( ! self::$_instance instanceof EE_Registry) {
213
+			self::$_instance = new EE_Registry($dependency_map);
214
+		}
215
+		return self::$_instance;
216
+	}
217
+
218
+
219
+
220
+	/**
221
+	 *protected constructor to prevent direct creation
222
+	 *
223
+	 * @Constructor
224
+	 * @access protected
225
+	 * @param  \EE_Dependency_Map $dependency_map
226
+	 */
227
+	protected function __construct(\EE_Dependency_Map $dependency_map)
228
+	{
229
+		$this->_dependency_map = $dependency_map;
230
+		$this->LIB = new stdClass();
231
+		$this->addons = new stdClass();
232
+		$this->modules = new stdClass();
233
+		$this->shortcodes = new stdClass();
234
+		$this->widgets = new stdClass();
235
+		add_action('EE_Load_Espresso_Core__handle_request__initialize_core_loading', array($this, 'initialize'));
236
+	}
237
+
238
+
239
+
240
+	/**
241
+	 * initialize
242
+	 */
243
+	public function initialize()
244
+	{
245
+		$this->_class_abbreviations = apply_filters(
246
+			'FHEE__EE_Registry____construct___class_abbreviations',
247
+			array(
248
+				'EE_Config'                                       => 'CFG',
249
+				'EE_Session'                                      => 'SSN',
250
+				'EE_Capabilities'                                 => 'CAP',
251
+				'EE_Cart'                                         => 'CART',
252
+				'EE_Network_Config'                               => 'NET_CFG',
253
+				'EE_Request_Handler'                              => 'REQ',
254
+				'EE_Message_Resource_Manager'                     => 'MRM',
255
+				'EventEspresso\core\services\commands\CommandBus' => 'BUS',
256
+				'EventEspresso\core\services\assets\Registry'     => 'AssetsRegistry',
257
+			)
258
+		);
259
+		$this->load_core('Base', array(), true);
260
+		// add our request and response objects to the cache
261
+		$request_loader = $this->_dependency_map->class_loader('EE_Request');
262
+		$this->_set_cached_class(
263
+			$request_loader(),
264
+			'EE_Request'
265
+		);
266
+		$response_loader = $this->_dependency_map->class_loader('EE_Response');
267
+		$this->_set_cached_class(
268
+			$response_loader(),
269
+			'EE_Response'
270
+		);
271
+		add_action('AHEE__EE_System__set_hooks_for_core', array($this, 'init'));
272
+	}
273
+
274
+
275
+
276
+	/**
277
+	 *    init
278
+	 *
279
+	 * @access    public
280
+	 * @return    void
281
+	 */
282
+	public function init()
283
+	{
284
+		// Get current page protocol
285
+		$protocol = isset($_SERVER['HTTPS']) ? 'https://' : 'http://';
286
+		// Output admin-ajax.php URL with same protocol as current page
287
+		self::$i18n_js_strings['ajax_url'] = admin_url('admin-ajax.php', $protocol);
288
+		self::$i18n_js_strings['wp_debug'] = defined('WP_DEBUG') ? WP_DEBUG : false;
289
+	}
290
+
291
+
292
+
293
+	/**
294
+	 * localize_i18n_js_strings
295
+	 *
296
+	 * @return string
297
+	 */
298
+	public static function localize_i18n_js_strings()
299
+	{
300
+		$i18n_js_strings = (array)EE_Registry::$i18n_js_strings;
301
+		foreach ($i18n_js_strings as $key => $value) {
302
+			if (is_scalar($value)) {
303
+				$i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
304
+			}
305
+		}
306
+		return "/* <![CDATA[ */ var eei18n = " . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
307
+	}
308
+
309
+
310
+
311
+	/**
312
+	 * @param mixed string | EED_Module $module
313
+	 */
314
+	public function add_module($module)
315
+	{
316
+		if ($module instanceof EED_Module) {
317
+			$module_class = get_class($module);
318
+			$this->modules->{$module_class} = $module;
319
+		} else {
320
+			if ( ! class_exists('EE_Module_Request_Router')) {
321
+				$this->load_core('Module_Request_Router');
322
+			}
323
+			$this->modules->{$module} = EE_Module_Request_Router::module_factory($module);
324
+		}
325
+	}
326
+
327
+
328
+
329
+	/**
330
+	 * @param string $module_name
331
+	 * @return mixed EED_Module | NULL
332
+	 */
333
+	public function get_module($module_name = '')
334
+	{
335
+		return isset($this->modules->{$module_name}) ? $this->modules->{$module_name} : null;
336
+	}
337
+
338
+
339
+
340
+	/**
341
+	 *    loads core classes - must be singletons
342
+	 *
343
+	 * @access    public
344
+	 * @param string $class_name - simple class name ie: session
345
+	 * @param mixed  $arguments
346
+	 * @param bool   $load_only
347
+	 * @return mixed
348
+	 */
349
+	public function load_core($class_name, $arguments = array(), $load_only = false)
350
+	{
351
+		$core_paths = apply_filters(
352
+			'FHEE__EE_Registry__load_core__core_paths',
353
+			array(
354
+				EE_CORE,
355
+				EE_ADMIN,
356
+				EE_CPTS,
357
+				EE_CORE . 'data_migration_scripts' . DS,
358
+				EE_CORE . 'request_stack' . DS,
359
+				EE_CORE . 'middleware' . DS,
360
+			)
361
+		);
362
+		// retrieve instantiated class
363
+		return $this->_load($core_paths, 'EE_', $class_name, 'core', $arguments, false, true, $load_only);
364
+	}
365
+
366
+
367
+
368
+	/**
369
+	 *    loads service classes
370
+	 *
371
+	 * @access    public
372
+	 * @param string $class_name - simple class name ie: session
373
+	 * @param mixed  $arguments
374
+	 * @param bool   $load_only
375
+	 * @return mixed
376
+	 */
377
+	public function load_service($class_name, $arguments = array(), $load_only = false)
378
+	{
379
+		$service_paths = apply_filters(
380
+			'FHEE__EE_Registry__load_service__service_paths',
381
+			array(
382
+				EE_CORE . 'services' . DS,
383
+			)
384
+		);
385
+		// retrieve instantiated class
386
+		return $this->_load($service_paths, 'EE_', $class_name, 'class', $arguments, false, true, $load_only);
387
+	}
388
+
389
+
390
+
391
+	/**
392
+	 *    loads data_migration_scripts
393
+	 *
394
+	 * @access    public
395
+	 * @param string $class_name - class name for the DMS ie: EE_DMS_Core_4_2_0
396
+	 * @param mixed  $arguments
397
+	 * @return EE_Data_Migration_Script_Base|mixed
398
+	 */
399
+	public function load_dms($class_name, $arguments = array())
400
+	{
401
+		// retrieve instantiated class
402
+		return $this->_load(EE_Data_Migration_Manager::instance()->get_data_migration_script_folders(), 'EE_DMS_', $class_name, 'dms', $arguments, false, false, false);
403
+	}
404
+
405
+
406
+
407
+	/**
408
+	 *    loads object creating classes - must be singletons
409
+	 *
410
+	 * @param string $class_name - simple class name ie: attendee
411
+	 * @param mixed  $arguments  - an array of arguments to pass to the class
412
+	 * @param bool   $from_db    - some classes are instantiated from the db and thus call a different method to instantiate
413
+	 * @param bool   $cache      if you don't want the class to be stored in the internal cache (non-persistent) then set this to FALSE (ie. when instantiating model objects from client in a loop)
414
+	 * @param bool   $load_only  whether or not to just load the file and NOT instantiate, or load AND instantiate (default)
415
+	 * @return EE_Base_Class | bool
416
+	 */
417
+	public function load_class($class_name, $arguments = array(), $from_db = false, $cache = true, $load_only = false)
418
+	{
419
+		$paths = apply_filters('FHEE__EE_Registry__load_class__paths', array(
420
+			EE_CORE,
421
+			EE_CLASSES,
422
+			EE_BUSINESS,
423
+		));
424
+		// retrieve instantiated class
425
+		return $this->_load($paths, 'EE_', $class_name, 'class', $arguments, $from_db, $cache, $load_only);
426
+	}
427
+
428
+
429
+
430
+	/**
431
+	 *    loads helper classes - must be singletons
432
+	 *
433
+	 * @param string $class_name - simple class name ie: price
434
+	 * @param mixed  $arguments
435
+	 * @param bool   $load_only
436
+	 * @return EEH_Base | bool
437
+	 */
438
+	public function load_helper($class_name, $arguments = array(), $load_only = true)
439
+	{
440
+		// todo: add doing_it_wrong() in a few versions after all addons have had calls to this method removed
441
+		$helper_paths = apply_filters('FHEE__EE_Registry__load_helper__helper_paths', array(EE_HELPERS));
442
+		// retrieve instantiated class
443
+		return $this->_load($helper_paths, 'EEH_', $class_name, 'helper', $arguments, false, true, $load_only);
444
+	}
445
+
446
+
447
+
448
+	/**
449
+	 *    loads core classes - must be singletons
450
+	 *
451
+	 * @access    public
452
+	 * @param string $class_name - simple class name ie: session
453
+	 * @param mixed  $arguments
454
+	 * @param bool   $load_only
455
+	 * @param bool   $cache      whether to cache the object or not.
456
+	 * @return mixed
457
+	 */
458
+	public function load_lib($class_name, $arguments = array(), $load_only = false, $cache = true)
459
+	{
460
+		$paths = array(
461
+			EE_LIBRARIES,
462
+			EE_LIBRARIES . 'messages' . DS,
463
+			EE_LIBRARIES . 'shortcodes' . DS,
464
+			EE_LIBRARIES . 'qtips' . DS,
465
+			EE_LIBRARIES . 'payment_methods' . DS,
466
+		);
467
+		// retrieve instantiated class
468
+		return $this->_load($paths, 'EE_', $class_name, 'lib', $arguments, false, $cache, $load_only);
469
+	}
470
+
471
+
472
+
473
+	/**
474
+	 *    loads model classes - must be singletons
475
+	 *
476
+	 * @param string $class_name - simple class name ie: price
477
+	 * @param mixed  $arguments
478
+	 * @param bool   $load_only
479
+	 * @return EEM_Base | bool
480
+	 */
481
+	public function load_model($class_name, $arguments = array(), $load_only = false)
482
+	{
483
+		$paths = apply_filters('FHEE__EE_Registry__load_model__paths', array(
484
+			EE_MODELS,
485
+			EE_CORE,
486
+		));
487
+		// retrieve instantiated class
488
+		return $this->_load($paths, 'EEM_', $class_name, 'model', $arguments, false, true, $load_only);
489
+	}
490
+
491
+
492
+
493
+	/**
494
+	 *    loads model classes - must be singletons
495
+	 *
496
+	 * @param string $class_name - simple class name ie: price
497
+	 * @param mixed  $arguments
498
+	 * @param bool   $load_only
499
+	 * @return mixed | bool
500
+	 */
501
+	public function load_model_class($class_name, $arguments = array(), $load_only = true)
502
+	{
503
+		$paths = array(
504
+			EE_MODELS . 'fields' . DS,
505
+			EE_MODELS . 'helpers' . DS,
506
+			EE_MODELS . 'relations' . DS,
507
+			EE_MODELS . 'strategies' . DS,
508
+		);
509
+		// retrieve instantiated class
510
+		return $this->_load($paths, 'EE_', $class_name, '', $arguments, false, true, $load_only);
511
+	}
512
+
513
+
514
+
515
+	/**
516
+	 * Determines if $model_name is the name of an actual EE model.
517
+	 *
518
+	 * @param string $model_name like Event, Attendee, Question_Group_Question, etc.
519
+	 * @return boolean
520
+	 */
521
+	public function is_model_name($model_name)
522
+	{
523
+		return isset($this->models[$model_name]) ? true : false;
524
+	}
525
+
526
+
527
+
528
+	/**
529
+	 *    generic class loader
530
+	 *
531
+	 * @param string $path_to_file - directory path to file location, not including filename
532
+	 * @param string $file_name    - file name  ie:  my_file.php, including extension
533
+	 * @param string $type         - file type - core? class? helper? model?
534
+	 * @param mixed  $arguments
535
+	 * @param bool   $load_only
536
+	 * @return mixed
537
+	 */
538
+	public function load_file($path_to_file, $file_name, $type = '', $arguments = array(), $load_only = true)
539
+	{
540
+		// retrieve instantiated class
541
+		return $this->_load($path_to_file, '', $file_name, $type, $arguments, false, true, $load_only);
542
+	}
543
+
544
+
545
+
546
+	/**
547
+	 *    load_addon
548
+	 *
549
+	 * @param string $path_to_file - directory path to file location, not including filename
550
+	 * @param string $class_name   - full class name  ie:  My_Class
551
+	 * @param string $type         - file type - core? class? helper? model?
552
+	 * @param mixed  $arguments
553
+	 * @param bool   $load_only
554
+	 * @return EE_Addon
555
+	 */
556
+	public function load_addon($path_to_file, $class_name, $type = 'class', $arguments = array(), $load_only = false)
557
+	{
558
+		// retrieve instantiated class
559
+		return $this->_load($path_to_file, 'addon', $class_name, $type, $arguments, false, true, $load_only);
560
+	}
561
+
562
+
563
+
564
+	/**
565
+	 * instantiates, caches, and automatically resolves dependencies
566
+	 * for classes that use a Fully Qualified Class Name.
567
+	 * if the class is not capable of being loaded using PSR-4 autoloading,
568
+	 * then you need to use one of the existing load_*() methods
569
+	 * which can resolve the classname and filepath from the passed arguments
570
+	 *
571
+	 * @param bool|string $class_name   Fully Qualified Class Name
572
+	 * @param array       $arguments    an argument, or array of arguments to pass to the class upon instantiation
573
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
574
+	 * @param bool        $from_db      some classes are instantiated from the db
575
+	 *                                  and thus call a different method to instantiate
576
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
577
+	 * @param bool|string $addon        if true, will cache the object in the EE_Registry->$addons array
578
+	 * @return mixed                    null = failure to load or instantiate class object.
579
+	 *                                  object = class loaded and instantiated successfully.
580
+	 *                                  bool = fail or success when $load_only is true
581
+	 */
582
+	public function create(
583
+		$class_name = false,
584
+		$arguments = array(),
585
+		$cache = false,
586
+		$from_db = false,
587
+		$load_only = false,
588
+		$addon = false
589
+	) {
590
+		$class_name = ltrim($class_name, '\\');
591
+		$class_name = $this->_dependency_map->get_alias($class_name);
592
+		if ( ! class_exists($class_name)) {
593
+			// maybe the class is registered with a preceding \
594
+			$class_name = strpos($class_name, '\\') !== 0 ? '\\' . $class_name : $class_name;
595
+			// still doesn't exist ?
596
+			if ( ! class_exists($class_name)) {
597
+				return null;
598
+			}
599
+		}
600
+		// if we're only loading the class and it already exists, then let's just return true immediately
601
+		if ($load_only) {
602
+			return true;
603
+		}
604
+		$addon = $addon ? 'addon' : '';
605
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
606
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
607
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
608
+		if ($this->_cache_on && $cache && ! $load_only) {
609
+			// return object if it's already cached
610
+			$cached_class = $this->_get_cached_class($class_name, $addon);
611
+			if ($cached_class !== null) {
612
+				return $cached_class;
613
+			}
614
+		}
615
+		// instantiate the requested object
616
+		$class_obj = $this->_create_object($class_name, $arguments, $addon, $from_db);
617
+		if ($this->_cache_on && $cache) {
618
+			// save it for later... kinda like gum  { : $
619
+			$this->_set_cached_class($class_obj, $class_name, $addon, $from_db);
620
+		}
621
+		$this->_cache_on = true;
622
+		return $class_obj;
623
+	}
624
+
625
+
626
+
627
+	/**
628
+	 * instantiates, caches, and injects dependencies for classes
629
+	 *
630
+	 * @param array       $file_paths   an array of paths to folders to look in
631
+	 * @param string      $class_prefix EE  or EEM or... ???
632
+	 * @param bool|string $class_name   $class name
633
+	 * @param string      $type         file type - core? class? helper? model?
634
+	 * @param mixed       $arguments    an argument or array of arguments to pass to the class upon instantiation
635
+	 * @param bool        $from_db      some classes are instantiated from the db
636
+	 *                                  and thus call a different method to instantiate
637
+	 * @param bool        $cache        whether to cache the instantiated object for reuse
638
+	 * @param bool        $load_only    if true, will only load the file, but will NOT instantiate an object
639
+	 * @return null|object|bool         null = failure to load or instantiate class object.
640
+	 *                                  object = class loaded and instantiated successfully.
641
+	 *                                  bool = fail or success when $load_only is true
642
+	 */
643
+	protected function _load(
644
+		$file_paths = array(),
645
+		$class_prefix = 'EE_',
646
+		$class_name = false,
647
+		$type = 'class',
648
+		$arguments = array(),
649
+		$from_db = false,
650
+		$cache = true,
651
+		$load_only = false
652
+	) {
653
+		$class_name = ltrim($class_name, '\\');
654
+		// strip php file extension
655
+		$class_name = str_replace('.php', '', trim($class_name));
656
+		// does the class have a prefix ?
657
+		if ( ! empty($class_prefix) && $class_prefix != 'addon') {
658
+			// make sure $class_prefix is uppercase
659
+			$class_prefix = strtoupper(trim($class_prefix));
660
+			// add class prefix ONCE!!!
661
+			$class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
662
+		}
663
+		$class_name = $this->_dependency_map->get_alias($class_name);
664
+		$class_exists = class_exists($class_name);
665
+		// if we're only loading the class and it already exists, then let's just return true immediately
666
+		if ($load_only && $class_exists) {
667
+			return true;
668
+		}
669
+		// $this->_cache_on is toggled during the recursive loading that can occur with dependency injection
670
+		// $cache is controlled by individual calls to separate Registry loader methods like load_class()
671
+		// $load_only is also controlled by individual calls to separate Registry loader methods like load_file()
672
+		if ($this->_cache_on && $cache && ! $load_only) {
673
+			// return object if it's already cached
674
+			$cached_class = $this->_get_cached_class($class_name, $class_prefix);
675
+			if ($cached_class !== null) {
676
+				return $cached_class;
677
+			}
678
+		}
679
+		// if the class doesn't already exist.. then we need to try and find the file and load it
680
+		if ( ! $class_exists) {
681
+			// get full path to file
682
+			$path = $this->_resolve_path($class_name, $type, $file_paths);
683
+			// load the file
684
+			$loaded = $this->_require_file($path, $class_name, $type, $file_paths);
685
+			// if loading failed, or we are only loading a file but NOT instantiating an object
686
+			if ( ! $loaded || $load_only) {
687
+				// return boolean if only loading, or null if an object was expected
688
+				return $load_only ? $loaded : null;
689
+			}
690
+		}
691
+		// instantiate the requested object
692
+		$class_obj = $this->_create_object($class_name, $arguments, $type, $from_db);
693
+		if ($this->_cache_on && $cache) {
694
+			// save it for later... kinda like gum  { : $
695
+			$this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db);
696
+		}
697
+		$this->_cache_on = true;
698
+		return $class_obj;
699
+	}
700
+
701
+
702
+
703
+
704
+	/**
705
+	 * _get_cached_class
706
+	 * attempts to find a cached version of the requested class
707
+	 * by looking in the following places:
708
+	 *        $this->{$class_abbreviation}            ie:    $this->CART
709
+	 *        $this->{$class_name}                        ie:    $this->Some_Class
710
+	 *        $this->LIB->{$class_name}                ie:    $this->LIB->Some_Class
711
+	 *        $this->addon->{$class_name}    ie:    $this->addon->Some_Addon_Class
712
+	 *
713
+	 * @access protected
714
+	 * @param string $class_name
715
+	 * @param string $class_prefix
716
+	 * @return mixed
717
+	 */
718
+	protected function _get_cached_class($class_name, $class_prefix = '')
719
+	{
720
+		if ($class_name === 'EE_Registry') {
721
+			return $this;
722
+		}
723
+		// have to specify something, but not anything that will conflict
724
+		$class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
725
+			? $this->_class_abbreviations[ $class_name ]
726
+			: 'FANCY_BATMAN_PANTS';
727
+		$class_name = str_replace('\\', '_', $class_name);
728
+		// check if class has already been loaded, and return it if it has been
729
+		if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
730
+			return $this->{$class_abbreviation};
731
+		}
732
+		if (isset ($this->{$class_name})) {
733
+			return $this->{$class_name};
734
+		}
735
+		if (isset ($this->LIB->{$class_name})) {
736
+			return $this->LIB->{$class_name};
737
+		}
738
+		if ($class_prefix === 'addon' && isset ($this->addons->{$class_name})) {
739
+			return $this->addons->{$class_name};
740
+		}
741
+		return null;
742
+	}
743
+
744
+
745
+
746
+	/**
747
+	 * removes a cached version of the requested class
748
+	 *
749
+	 * @param string $class_name
750
+	 * @param boolean $addon
751
+	 * @return boolean
752
+	 */
753
+	public function clear_cached_class($class_name, $addon = false)
754
+	{
755
+		// have to specify something, but not anything that will conflict
756
+		$class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
757
+			? $this->_class_abbreviations[ $class_name ]
758
+			: 'FANCY_BATMAN_PANTS';
759
+		$class_name = str_replace('\\', '_', $class_name);
760
+		// check if class has already been loaded, and return it if it has been
761
+		if (isset($this->{$class_abbreviation}) && ! is_null($this->{$class_abbreviation})) {
762
+			$this->{$class_abbreviation} = null;
763
+			return true;
764
+		}
765
+		if (isset($this->{$class_name})) {
766
+			$this->{$class_name} = null;
767
+			return true;
768
+		}
769
+		if (isset($this->LIB->{$class_name})) {
770
+			unset($this->LIB->{$class_name});
771
+			return true;
772
+		}
773
+		if ($addon && isset($this->addons->{$class_name})) {
774
+			unset($this->addons->{$class_name});
775
+			return true;
776
+		}
777
+		return false;
778
+	}
779
+
780
+
781
+	/**
782
+	 * _resolve_path
783
+	 * attempts to find a full valid filepath for the requested class.
784
+	 * loops thru each of the base paths in the $file_paths array and appends : "{classname} . {file type} . php"
785
+	 * then returns that path if the target file has been found and is readable
786
+	 *
787
+	 * @access protected
788
+	 * @param string $class_name
789
+	 * @param string $type
790
+	 * @param array  $file_paths
791
+	 * @return string | bool
792
+	 */
793
+	protected function _resolve_path($class_name, $type = '', $file_paths = array())
794
+	{
795
+		// make sure $file_paths is an array
796
+		$file_paths = is_array($file_paths) ? $file_paths : array($file_paths);
797
+		// cycle thru paths
798
+		foreach ($file_paths as $key => $file_path) {
799
+			// convert all separators to proper DS, if no filepath, then use EE_CLASSES
800
+			$file_path = $file_path ? str_replace(array('/', '\\'), DS, $file_path) : EE_CLASSES;
801
+			// prep file type
802
+			$type = ! empty($type) ? trim($type, '.') . '.' : '';
803
+			// build full file path
804
+			$file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
805
+			//does the file exist and can be read ?
806
+			if (is_readable($file_paths[$key])) {
807
+				return $file_paths[$key];
808
+			}
809
+		}
810
+		return false;
811
+	}
812
+
813
+
814
+
815
+	/**
816
+	 * _require_file
817
+	 * basically just performs a require_once()
818
+	 * but with some error handling
819
+	 *
820
+	 * @access protected
821
+	 * @param  string $path
822
+	 * @param  string $class_name
823
+	 * @param  string $type
824
+	 * @param  array  $file_paths
825
+	 * @return boolean
826
+	 * @throws \EE_Error
827
+	 */
828
+	protected function _require_file($path, $class_name, $type = '', $file_paths = array())
829
+	{
830
+		// don't give up! you gotta...
831
+		try {
832
+			//does the file exist and can it be read ?
833
+			if ( ! $path) {
834
+				// so sorry, can't find the file
835
+				throw new EE_Error (
836
+					sprintf(
837
+						__('The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s', 'event_espresso'),
838
+						trim($type, '.'),
839
+						$class_name,
840
+						'<br />' . implode(',<br />', $file_paths)
841
+					)
842
+				);
843
+			}
844
+			// get the file
845
+			require_once($path);
846
+			// if the class isn't already declared somewhere
847
+			if (class_exists($class_name, false) === false) {
848
+				// so sorry, not a class
849
+				throw new EE_Error(
850
+					sprintf(
851
+						__('The %s file %s does not appear to contain the %s Class.', 'event_espresso'),
852
+						$type,
853
+						$path,
854
+						$class_name
855
+					)
856
+				);
857
+			}
858
+		} catch (EE_Error $e) {
859
+			$e->get_error();
860
+			return false;
861
+		}
862
+		return true;
863
+	}
864
+
865
+
866
+
867
+	/**
868
+	 * _create_object
869
+	 * Attempts to instantiate the requested class via any of the
870
+	 * commonly used instantiation methods employed throughout EE.
871
+	 * The priority for instantiation is as follows:
872
+	 *        - abstract classes or any class flagged as "load only" (no instantiation occurs)
873
+	 *        - model objects via their 'new_instance_from_db' method
874
+	 *        - model objects via their 'new_instance' method
875
+	 *        - "singleton" classes" via their 'instance' method
876
+	 *    - standard instantiable classes via their __constructor
877
+	 * Prior to instantiation, if the classname exists in the dependency_map,
878
+	 * then the constructor for the requested class will be examined to determine
879
+	 * if any dependencies exist, and if they can be injected.
880
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
881
+	 *
882
+	 * @access protected
883
+	 * @param string $class_name
884
+	 * @param array  $arguments
885
+	 * @param string $type
886
+	 * @param bool   $from_db
887
+	 * @return null | object
888
+	 * @throws \EE_Error
889
+	 */
890
+	protected function _create_object($class_name, $arguments = array(), $type = '', $from_db = false)
891
+	{
892
+		$class_obj = null;
893
+		$instantiation_mode = '0) none';
894
+		// don't give up! you gotta...
895
+		try {
896
+			// create reflection
897
+			$reflector = $this->get_ReflectionClass($class_name);
898
+			// make sure arguments are an array
899
+			$arguments = is_array($arguments) ? $arguments : array($arguments);
900
+			// and if arguments array is numerically and sequentially indexed, then we want it to remain as is,
901
+			// else wrap it in an additional array so that it doesn't get split into multiple parameters
902
+			$arguments = $this->_array_is_numerically_and_sequentially_indexed($arguments)
903
+				? $arguments
904
+				: array($arguments);
905
+			// attempt to inject dependencies ?
906
+			if ($this->_dependency_map->has($class_name)) {
907
+				$arguments = $this->_resolve_dependencies($reflector, $class_name, $arguments);
908
+			}
909
+			// instantiate the class if possible
910
+			if ($reflector->isAbstract()) {
911
+				// nothing to instantiate, loading file was enough
912
+				// does not throw an exception so $instantiation_mode is unused
913
+				// $instantiation_mode = "1) no constructor abstract class";
914
+				$class_obj = true;
915
+			} else if ($reflector->getConstructor() === null && $reflector->isInstantiable() && empty($arguments)) {
916
+				// no constructor = static methods only... nothing to instantiate, loading file was enough
917
+				$instantiation_mode = "2) no constructor but instantiable";
918
+				$class_obj = $reflector->newInstance();
919
+			} else if ($from_db && method_exists($class_name, 'new_instance_from_db')) {
920
+				$instantiation_mode = "3) new_instance_from_db()";
921
+				$class_obj = call_user_func_array(array($class_name, 'new_instance_from_db'), $arguments);
922
+			} else if (method_exists($class_name, 'new_instance')) {
923
+				$instantiation_mode = "4) new_instance()";
924
+				$class_obj = call_user_func_array(array($class_name, 'new_instance'), $arguments);
925
+			} else if (method_exists($class_name, 'instance')) {
926
+				$instantiation_mode = "5) instance()";
927
+				$class_obj = call_user_func_array(array($class_name, 'instance'), $arguments);
928
+			} else if ($reflector->isInstantiable()) {
929
+				$instantiation_mode = "6) constructor";
930
+				$class_obj = $reflector->newInstanceArgs($arguments);
931
+			} else {
932
+				// heh ? something's not right !
933
+				throw new EE_Error(
934
+					sprintf(
935
+						__('The %s file %s could not be instantiated.', 'event_espresso'),
936
+						$type,
937
+						$class_name
938
+					)
939
+				);
940
+			}
941
+		} catch (Exception $e) {
942
+			if ( ! $e instanceof EE_Error) {
943
+				$e = new EE_Error(
944
+					sprintf(
945
+						__('The following error occurred while attempting to instantiate "%1$s": %2$s %3$s %2$s instantiation mode : %4$s', 'event_espresso'),
946
+						$class_name,
947
+						'<br />',
948
+						$e->getMessage(),
949
+						$instantiation_mode
950
+					)
951
+				);
952
+			}
953
+			$e->get_error();
954
+		}
955
+		return $class_obj;
956
+	}
957
+
958
+
959
+
960
+	/**
961
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
962
+	 * @param array $array
963
+	 * @return bool
964
+	 */
965
+	protected function _array_is_numerically_and_sequentially_indexed(array $array)
966
+	{
967
+		return ! empty($array) ? array_keys($array) === range(0, count($array) - 1) : true;
968
+	}
969
+
970
+
971
+
972
+	/**
973
+	 * getReflectionClass
974
+	 * checks if a ReflectionClass object has already been generated for a class
975
+	 * and returns that instead of creating a new one
976
+	 *
977
+	 * @access public
978
+	 * @param string $class_name
979
+	 * @return ReflectionClass
980
+	 */
981
+	public function get_ReflectionClass($class_name)
982
+	{
983
+		if (
984
+			! isset($this->_reflectors[$class_name])
985
+			|| ! $this->_reflectors[$class_name] instanceof ReflectionClass
986
+		) {
987
+			$this->_reflectors[$class_name] = new ReflectionClass($class_name);
988
+		}
989
+		return $this->_reflectors[$class_name];
990
+	}
991
+
992
+
993
+
994
+	/**
995
+	 * _resolve_dependencies
996
+	 * examines the constructor for the requested class to determine
997
+	 * if any dependencies exist, and if they can be injected.
998
+	 * If so, then those classes will be added to the array of arguments passed to the constructor
999
+	 * PLZ NOTE: this is achieved by type hinting the constructor params
1000
+	 * For example:
1001
+	 *        if attempting to load a class "Foo" with the following constructor:
1002
+	 *        __construct( Bar $bar_class, Fighter $grohl_class )
1003
+	 *        then $bar_class and $grohl_class will be added to the $arguments array,
1004
+	 *        but only IF they are NOT already present in the incoming arguments array,
1005
+	 *        and the correct classes can be loaded
1006
+	 *
1007
+	 * @access protected
1008
+	 * @param ReflectionClass $reflector
1009
+	 * @param string          $class_name
1010
+	 * @param array           $arguments
1011
+	 * @return array
1012
+	 * @throws \ReflectionException
1013
+	 */
1014
+	protected function _resolve_dependencies(ReflectionClass $reflector, $class_name, $arguments = array())
1015
+	{
1016
+		// let's examine the constructor
1017
+		$constructor = $reflector->getConstructor();
1018
+		// whu? huh? nothing?
1019
+		if ( ! $constructor) {
1020
+			return $arguments;
1021
+		}
1022
+		// get constructor parameters
1023
+		$params = $constructor->getParameters();
1024
+		// and the keys for the incoming arguments array so that we can compare existing arguments with what is expected
1025
+		$argument_keys = array_keys($arguments);
1026
+		// now loop thru all of the constructors expected parameters
1027
+		foreach ($params as $index => $param) {
1028
+			// is this a dependency for a specific class ?
1029
+			$param_class = $param->getClass() ? $param->getClass()->name : null;
1030
+			// BUT WAIT !!! This class may be an alias for something else (or getting replaced at runtime)
1031
+			$param_class = $this->_dependency_map->has_alias($param_class, $class_name)
1032
+				? $this->_dependency_map->get_alias($param_class, $class_name)
1033
+				: $param_class;
1034
+			if (
1035
+				// param is not even a class
1036
+				empty($param_class)
1037
+				// and something already exists in the incoming arguments for this param
1038
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1039
+			) {
1040
+				// so let's skip this argument and move on to the next
1041
+				continue;
1042
+			}
1043
+			if (
1044
+				// parameter is type hinted as a class, exists as an incoming argument, AND it's the correct class
1045
+				! empty($param_class)
1046
+				&& isset($argument_keys[$index], $arguments[$argument_keys[$index]])
1047
+				&& $arguments[$argument_keys[$index]] instanceof $param_class
1048
+			) {
1049
+				// skip this argument and move on to the next
1050
+				continue;
1051
+			}
1052
+			if (
1053
+				// parameter is type hinted as a class, and should be injected
1054
+				! empty($param_class)
1055
+				&& $this->_dependency_map->has_dependency_for_class($class_name, $param_class)
1056
+			) {
1057
+				$arguments = $this->_resolve_dependency($class_name, $param_class, $arguments, $index);
1058
+			} else {
1059
+				try {
1060
+					$arguments[$index] = $param->getDefaultValue();
1061
+				} catch (ReflectionException $e) {
1062
+					throw new ReflectionException(
1063
+						sprintf(
1064
+							__('%1$s for parameter "$%2$s"', 'event_espresso'),
1065
+							$e->getMessage(),
1066
+							$param->getName()
1067
+						)
1068
+					);
1069
+				}
1070
+			}
1071
+		}
1072
+		return $arguments;
1073
+	}
1074
+
1075
+
1076
+
1077
+	/**
1078
+	 * @access protected
1079
+	 * @param string $class_name
1080
+	 * @param string $param_class
1081
+	 * @param array  $arguments
1082
+	 * @param mixed  $index
1083
+	 * @return array
1084
+	 */
1085
+	protected function _resolve_dependency($class_name, $param_class, $arguments, $index)
1086
+	{
1087
+		$dependency = null;
1088
+		// should dependency be loaded from cache ?
1089
+		$cache_on = $this->_dependency_map->loading_strategy_for_class_dependency($class_name, $param_class)
1090
+					!== EE_Dependency_Map::load_new_object
1091
+			? true
1092
+			: false;
1093
+		// we might have a dependency...
1094
+		// let's MAYBE try and find it in our cache if that's what's been requested
1095
+		$cached_class = $cache_on ? $this->_get_cached_class($param_class) : null;
1096
+		// and grab it if it exists
1097
+		if ($cached_class instanceof $param_class) {
1098
+			$dependency = $cached_class;
1099
+		} else if ($param_class !== $class_name) {
1100
+			// obtain the loader method from the dependency map
1101
+			$loader = $this->_dependency_map->class_loader($param_class);
1102
+			// is loader a custom closure ?
1103
+			if ($loader instanceof Closure) {
1104
+				$dependency = $loader();
1105
+			} else {
1106
+				// set the cache on property for the recursive loading call
1107
+				$this->_cache_on = $cache_on;
1108
+				// if not, then let's try and load it via the registry
1109
+				if ($loader && method_exists($this, $loader)) {
1110
+					$dependency = $this->{$loader}($param_class);
1111
+				} else {
1112
+					$dependency = $this->create($param_class, array(), $cache_on);
1113
+				}
1114
+			}
1115
+		}
1116
+		// did we successfully find the correct dependency ?
1117
+		if ($dependency instanceof $param_class) {
1118
+			// then let's inject it into the incoming array of arguments at the correct location
1119
+			if (isset($argument_keys[$index])) {
1120
+				$arguments[$argument_keys[$index]] = $dependency;
1121
+			} else {
1122
+				$arguments[$index] = $dependency;
1123
+			}
1124
+		}
1125
+		return $arguments;
1126
+	}
1127
+
1128
+
1129
+
1130
+	/**
1131
+	 * _set_cached_class
1132
+	 * attempts to cache the instantiated class locally
1133
+	 * in one of the following places, in the following order:
1134
+	 *        $this->{class_abbreviation}   ie:    $this->CART
1135
+	 *        $this->{$class_name}          ie:    $this->Some_Class
1136
+	 *        $this->addon->{$$class_name}    ie:    $this->addon->Some_Addon_Class
1137
+	 *        $this->LIB->{$class_name}     ie:    $this->LIB->Some_Class
1138
+	 *
1139
+	 * @access protected
1140
+	 * @param object $class_obj
1141
+	 * @param string $class_name
1142
+	 * @param string $class_prefix
1143
+	 * @param bool   $from_db
1144
+	 * @return void
1145
+	 */
1146
+	protected function _set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false)
1147
+	{
1148
+		if ($class_name === 'EE_Registry' || empty($class_obj)) {
1149
+			return;
1150
+		}
1151
+		// return newly instantiated class
1152
+		if (isset($this->_class_abbreviations[$class_name])) {
1153
+			$class_abbreviation = $this->_class_abbreviations[$class_name];
1154
+			$this->{$class_abbreviation} = $class_obj;
1155
+			return;
1156
+		}
1157
+		$class_name = str_replace('\\', '_', $class_name);
1158
+		if (property_exists($this, $class_name)) {
1159
+			$this->{$class_name} = $class_obj;
1160
+			return;
1161
+		}
1162
+		if ($class_prefix === 'addon') {
1163
+			$this->addons->{$class_name} = $class_obj;
1164
+			return;
1165
+		}
1166
+		if ( ! $from_db) {
1167
+			$this->LIB->{$class_name} = $class_obj;
1168
+		}
1169
+	}
1170
+
1171
+
1172
+
1173
+	/**
1174
+	 * call any loader that's been registered in the EE_Dependency_Map::$_class_loaders array
1175
+	 *
1176
+	 * @param string $classname PLEASE NOTE: the class name needs to match what's registered
1177
+	 *                          in the EE_Dependency_Map::$_class_loaders array,
1178
+	 *                          including the class prefix, ie: "EE_", "EEM_", "EEH_", etc
1179
+	 * @param array  $arguments
1180
+	 * @return object
1181
+	 */
1182
+	public static function factory($classname, $arguments = array())
1183
+	{
1184
+		$loader = self::instance()->_dependency_map->class_loader($classname);
1185
+		if ($loader instanceof Closure) {
1186
+			return $loader($arguments);
1187
+		}
1188
+		if (method_exists(EE_Registry::instance(), $loader)) {
1189
+			return EE_Registry::instance()->{$loader}($classname, $arguments);
1190
+		}
1191
+		return null;
1192
+	}
1193
+
1194
+
1195
+
1196
+	/**
1197
+	 * Gets the addon by its name/slug (not classname. For that, just
1198
+	 * use the classname as the property name on EE_Config::instance()->addons)
1199
+	 *
1200
+	 * @param string $name
1201
+	 * @return EE_Addon
1202
+	 */
1203
+	public function get_addon_by_name($name)
1204
+	{
1205
+		foreach ($this->addons as $addon) {
1206
+			if ($addon->name() == $name) {
1207
+				return $addon;
1208
+			}
1209
+		}
1210
+		return null;
1211
+	}
1212
+
1213
+
1214
+
1215
+	/**
1216
+	 * Gets an array of all the registered addons, where the keys are their names. (ie, what each returns for their name() function) They're already available on EE_Config::instance()->addons as properties, where each property's name is
1217
+	 * the addon's classname. So if you just want to get the addon by classname, use EE_Config::instance()->addons->{classname}
1218
+	 *
1219
+	 * @return EE_Addon[] where the KEYS are the addon's name()
1220
+	 */
1221
+	public function get_addons_by_name()
1222
+	{
1223
+		$addons = array();
1224
+		foreach ($this->addons as $addon) {
1225
+			$addons[$addon->name()] = $addon;
1226
+		}
1227
+		return $addons;
1228
+	}
1229
+
1230
+
1231
+
1232
+	/**
1233
+	 * Resets the specified model's instance AND makes sure EE_Registry doesn't keep
1234
+	 * a stale copy of it around
1235
+	 *
1236
+	 * @param string $model_name
1237
+	 * @return \EEM_Base
1238
+	 * @throws \EE_Error
1239
+	 */
1240
+	public function reset_model($model_name)
1241
+	{
1242
+		$model_class_name = strpos($model_name, 'EEM_') !== 0 ? "EEM_{$model_name}" : $model_name;
1243
+		if ( ! isset($this->LIB->{$model_class_name}) || ! $this->LIB->{$model_class_name} instanceof EEM_Base) {
1244
+			return null;
1245
+		}
1246
+		//get that model reset it and make sure we nuke the old reference to it
1247
+		if ($this->LIB->{$model_class_name} instanceof $model_class_name && is_callable(array($model_class_name, 'reset'))) {
1248
+			$this->LIB->{$model_class_name} = $this->LIB->{$model_class_name}->reset();
1249
+		} else {
1250
+			throw new EE_Error(sprintf(__('Model %s does not have a method "reset"', 'event_espresso'), $model_name));
1251
+		}
1252
+		return $this->LIB->{$model_class_name};
1253
+	}
1254
+
1255
+
1256
+
1257
+	/**
1258
+	 * Resets the registry.
1259
+	 * The criteria for what gets reset is based on what can be shared between sites on the same request when switch_to_blog
1260
+	 * is used in a multisite install.  Here is a list of things that are NOT reset.
1261
+	 * - $_dependency_map
1262
+	 * - $_class_abbreviations
1263
+	 * - $NET_CFG (EE_Network_Config): The config is shared network wide so no need to reset.
1264
+	 * - $REQ:  Still on the same request so no need to change.
1265
+	 * - $CAP: There is no site specific state in the EE_Capability class.
1266
+	 * - $SSN: Although ideally, the session should not be shared between site switches, we can't reset it because only one Session
1267
+	 *         can be active in a single request.  Resetting could resolve in "headers already sent" errors.
1268
+	 * - $addons:  In multisite, the state of the addons is something controlled via hooks etc in a normal request.  So
1269
+	 *             for now, we won't reset the addons because it could break calls to an add-ons class/methods in the
1270
+	 *             switch or on the restore.
1271
+	 * - $modules
1272
+	 * - $shortcodes
1273
+	 * - $widgets
1274
+	 *
1275
+	 * @param boolean $hard             whether to reset data in the database too, or just refresh
1276
+	 *                                  the Registry to its state at the beginning of the request
1277
+	 * @param boolean $reinstantiate    whether to create new instances of EE_Registry's singletons too,
1278
+	 *                                  or just reset without re-instantiating (handy to set to FALSE if you're not sure if you CAN
1279
+	 *                                  currently reinstantiate the singletons at the moment)
1280
+	 * @param   bool  $reset_models     Defaults to true.  When false, then the models are not reset.  This is so client
1281
+	 *                                  code instead can just change the model context to a different blog id if necessary
1282
+	 * @return EE_Registry
1283
+	 */
1284
+	public static function reset($hard = false, $reinstantiate = true, $reset_models = true)
1285
+	{
1286
+		$instance = self::instance();
1287
+		$instance->_cache_on = true;
1288
+		// reset some "special" classes
1289
+		EEH_Activation::reset();
1290
+		$instance->CFG = $instance->CFG->reset($hard, $reinstantiate);
1291
+		$instance->CART = null;
1292
+		$instance->MRM = null;
1293
+		$instance->AssetsRegistry = null;
1294
+		$instance->AssetsRegistry = $instance->create('EventEspresso\core\services\assets\Registry');
1295
+		//messages reset
1296
+		EED_Messages::reset();
1297
+		//handle of objects cached on LIB
1298
+		foreach (array('LIB', 'modules', 'shortcodes') as $cache) {
1299
+			foreach ($instance->{$cache} as $class_name => $class) {
1300
+				if (EE_Registry::_reset_and_unset_object($class, $reset_models)) {
1301
+					unset($instance->{$cache}->{$class_name});
1302
+				}
1303
+			}
1304
+		}
1305
+		return $instance;
1306
+	}
1307
+
1308
+
1309
+
1310
+	/**
1311
+	 * if passed object implements ResettableInterface, then call it's reset() method
1312
+	 * if passed object implements InterminableInterface, then return false,
1313
+	 * to indicate that it should NOT be cleared from the Registry cache
1314
+	 *
1315
+	 * @param      $object
1316
+	 * @param bool $reset_models
1317
+	 * @return bool returns true if cached object should be unset
1318
+	 */
1319
+	private static function _reset_and_unset_object($object, $reset_models)
1320
+	{
1321
+		static $count = 0;
1322
+		$count++;
1323
+		if ($object instanceof ResettableInterface) {
1324
+			if ($object instanceof EEM_Base) {
1325
+				if ($reset_models) {
1326
+					$object->reset();
1327
+					return true;
1328
+				}
1329
+				return false;
1330
+			}
1331
+			$object->reset();
1332
+			return true;
1333
+		}
1334
+		if ( ! $object instanceof InterminableInterface) {
1335
+			return true;
1336
+		}
1337
+		return false;
1338
+	}
1339
+
1340
+
1341
+
1342
+	/**
1343
+	 * @override magic methods
1344
+	 * @return void
1345
+	 */
1346
+	public final function __destruct()
1347
+	{
1348
+	}
1349
+
1350
+
1351
+
1352
+	/**
1353
+	 * @param $a
1354
+	 * @param $b
1355
+	 */
1356
+	public final function __call($a, $b)
1357
+	{
1358
+	}
1359
+
1360
+
1361
+
1362
+	/**
1363
+	 * @param $a
1364
+	 */
1365
+	public final function __get($a)
1366
+	{
1367
+	}
1368
+
1369
+
1370
+
1371
+	/**
1372
+	 * @param $a
1373
+	 * @param $b
1374
+	 */
1375
+	public final function __set($a, $b)
1376
+	{
1377
+	}
1378
+
1379
+
1380
+
1381
+	/**
1382
+	 * @param $a
1383
+	 */
1384
+	public final function __isset($a)
1385
+	{
1386
+	}
1387 1387
 
1388 1388
 
1389 1389
 
1390
-    /**
1391
-     * @param $a
1392
-     */
1393
-    public final function __unset($a)
1394
-    {
1395
-    }
1390
+	/**
1391
+	 * @param $a
1392
+	 */
1393
+	public final function __unset($a)
1394
+	{
1395
+	}
1396 1396
 
1397 1397
 
1398 1398
 
1399
-    /**
1400
-     * @return array
1401
-     */
1402
-    public final function __sleep()
1403
-    {
1404
-        return array();
1405
-    }
1399
+	/**
1400
+	 * @return array
1401
+	 */
1402
+	public final function __sleep()
1403
+	{
1404
+		return array();
1405
+	}
1406 1406
 
1407 1407
 
1408 1408
 
1409
-    public final function __wakeup()
1410
-    {
1411
-    }
1409
+	public final function __wakeup()
1410
+	{
1411
+	}
1412 1412
 
1413 1413
 
1414 1414
 
1415
-    /**
1416
-     * @return string
1417
-     */
1418
-    public final function __toString()
1419
-    {
1420
-        return '';
1421
-    }
1415
+	/**
1416
+	 * @return string
1417
+	 */
1418
+	public final function __toString()
1419
+	{
1420
+		return '';
1421
+	}
1422 1422
 
1423 1423
 
1424 1424
 
1425
-    public final function __invoke()
1426
-    {
1427
-    }
1425
+	public final function __invoke()
1426
+	{
1427
+	}
1428 1428
 
1429 1429
 
1430 1430
 
1431
-    public final static function __set_state($array = array())
1432
-    {
1433
-        return EE_Registry::instance();
1434
-    }
1431
+	public final static function __set_state($array = array())
1432
+	{
1433
+		return EE_Registry::instance();
1434
+	}
1435 1435
 
1436 1436
 
1437 1437
 
1438
-    public final function __clone()
1439
-    {
1440
-    }
1438
+	public final function __clone()
1439
+	{
1440
+	}
1441 1441
 
1442 1442
 
1443 1443
 
1444
-    /**
1445
-     * @param $a
1446
-     * @param $b
1447
-     */
1448
-    public final static function __callStatic($a, $b)
1449
-    {
1450
-    }
1444
+	/**
1445
+	 * @param $a
1446
+	 * @param $b
1447
+	 */
1448
+	public final static function __callStatic($a, $b)
1449
+	{
1450
+	}
1451 1451
 
1452 1452
 
1453 1453
 
1454
-    /**
1455
-     * Gets all the custom post type models defined
1456
-     *
1457
-     * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1458
-     */
1459
-    public function cpt_models()
1460
-    {
1461
-        $cpt_models = array();
1462
-        foreach ($this->non_abstract_db_models as $short_name => $classname) {
1463
-            if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1464
-                $cpt_models[$short_name] = $classname;
1465
-            }
1466
-        }
1467
-        return $cpt_models;
1468
-    }
1454
+	/**
1455
+	 * Gets all the custom post type models defined
1456
+	 *
1457
+	 * @return array keys are model "short names" (Eg "Event") and keys are classnames (eg "EEM_Event")
1458
+	 */
1459
+	public function cpt_models()
1460
+	{
1461
+		$cpt_models = array();
1462
+		foreach ($this->non_abstract_db_models as $short_name => $classname) {
1463
+			if (is_subclass_of($classname, 'EEM_CPT_Base')) {
1464
+				$cpt_models[$short_name] = $classname;
1465
+			}
1466
+		}
1467
+		return $cpt_models;
1468
+	}
1469 1469
 
1470 1470
 
1471 1471
 
1472
-    /**
1473
-     * @return \EE_Config
1474
-     */
1475
-    public static function CFG()
1476
-    {
1477
-        return self::instance()->CFG;
1478
-    }
1472
+	/**
1473
+	 * @return \EE_Config
1474
+	 */
1475
+	public static function CFG()
1476
+	{
1477
+		return self::instance()->CFG;
1478
+	}
1479 1479
 
1480 1480
 
1481 1481
 }
Please login to merge, or discard this patch.
Spacing   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -297,13 +297,13 @@  discard block
 block discarded – undo
297 297
      */
298 298
     public static function localize_i18n_js_strings()
299 299
     {
300
-        $i18n_js_strings = (array)EE_Registry::$i18n_js_strings;
300
+        $i18n_js_strings = (array) EE_Registry::$i18n_js_strings;
301 301
         foreach ($i18n_js_strings as $key => $value) {
302 302
             if (is_scalar($value)) {
303
-                $i18n_js_strings[$key] = html_entity_decode((string)$value, ENT_QUOTES, 'UTF-8');
303
+                $i18n_js_strings[$key] = html_entity_decode((string) $value, ENT_QUOTES, 'UTF-8');
304 304
             }
305 305
         }
306
-        return "/* <![CDATA[ */ var eei18n = " . wp_json_encode($i18n_js_strings) . '; /* ]]> */';
306
+        return "/* <![CDATA[ */ var eei18n = ".wp_json_encode($i18n_js_strings).'; /* ]]> */';
307 307
     }
308 308
 
309 309
 
@@ -354,9 +354,9 @@  discard block
 block discarded – undo
354 354
                 EE_CORE,
355 355
                 EE_ADMIN,
356 356
                 EE_CPTS,
357
-                EE_CORE . 'data_migration_scripts' . DS,
358
-                EE_CORE . 'request_stack' . DS,
359
-                EE_CORE . 'middleware' . DS,
357
+                EE_CORE.'data_migration_scripts'.DS,
358
+                EE_CORE.'request_stack'.DS,
359
+                EE_CORE.'middleware'.DS,
360 360
             )
361 361
         );
362 362
         // retrieve instantiated class
@@ -379,7 +379,7 @@  discard block
 block discarded – undo
379 379
         $service_paths = apply_filters(
380 380
             'FHEE__EE_Registry__load_service__service_paths',
381 381
             array(
382
-                EE_CORE . 'services' . DS,
382
+                EE_CORE.'services'.DS,
383 383
             )
384 384
         );
385 385
         // retrieve instantiated class
@@ -459,10 +459,10 @@  discard block
 block discarded – undo
459 459
     {
460 460
         $paths = array(
461 461
             EE_LIBRARIES,
462
-            EE_LIBRARIES . 'messages' . DS,
463
-            EE_LIBRARIES . 'shortcodes' . DS,
464
-            EE_LIBRARIES . 'qtips' . DS,
465
-            EE_LIBRARIES . 'payment_methods' . DS,
462
+            EE_LIBRARIES.'messages'.DS,
463
+            EE_LIBRARIES.'shortcodes'.DS,
464
+            EE_LIBRARIES.'qtips'.DS,
465
+            EE_LIBRARIES.'payment_methods'.DS,
466 466
         );
467 467
         // retrieve instantiated class
468 468
         return $this->_load($paths, 'EE_', $class_name, 'lib', $arguments, false, $cache, $load_only);
@@ -501,10 +501,10 @@  discard block
 block discarded – undo
501 501
     public function load_model_class($class_name, $arguments = array(), $load_only = true)
502 502
     {
503 503
         $paths = array(
504
-            EE_MODELS . 'fields' . DS,
505
-            EE_MODELS . 'helpers' . DS,
506
-            EE_MODELS . 'relations' . DS,
507
-            EE_MODELS . 'strategies' . DS,
504
+            EE_MODELS.'fields'.DS,
505
+            EE_MODELS.'helpers'.DS,
506
+            EE_MODELS.'relations'.DS,
507
+            EE_MODELS.'strategies'.DS,
508 508
         );
509 509
         // retrieve instantiated class
510 510
         return $this->_load($paths, 'EE_', $class_name, '', $arguments, false, true, $load_only);
@@ -591,7 +591,7 @@  discard block
 block discarded – undo
591 591
         $class_name = $this->_dependency_map->get_alias($class_name);
592 592
         if ( ! class_exists($class_name)) {
593 593
             // maybe the class is registered with a preceding \
594
-            $class_name = strpos($class_name, '\\') !== 0 ? '\\' . $class_name : $class_name;
594
+            $class_name = strpos($class_name, '\\') !== 0 ? '\\'.$class_name : $class_name;
595 595
             // still doesn't exist ?
596 596
             if ( ! class_exists($class_name)) {
597 597
                 return null;
@@ -658,7 +658,7 @@  discard block
 block discarded – undo
658 658
             // make sure $class_prefix is uppercase
659 659
             $class_prefix = strtoupper(trim($class_prefix));
660 660
             // add class prefix ONCE!!!
661
-            $class_name = $class_prefix . str_replace($class_prefix, '', $class_name);
661
+            $class_name = $class_prefix.str_replace($class_prefix, '', $class_name);
662 662
         }
663 663
         $class_name = $this->_dependency_map->get_alias($class_name);
664 664
         $class_exists = class_exists($class_name);
@@ -721,8 +721,8 @@  discard block
 block discarded – undo
721 721
             return $this;
722 722
         }
723 723
         // have to specify something, but not anything that will conflict
724
-        $class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
725
-            ? $this->_class_abbreviations[ $class_name ]
724
+        $class_abbreviation = isset($this->_class_abbreviations[$class_name])
725
+            ? $this->_class_abbreviations[$class_name]
726 726
             : 'FANCY_BATMAN_PANTS';
727 727
         $class_name = str_replace('\\', '_', $class_name);
728 728
         // check if class has already been loaded, and return it if it has been
@@ -753,8 +753,8 @@  discard block
 block discarded – undo
753 753
     public function clear_cached_class($class_name, $addon = false)
754 754
     {
755 755
         // have to specify something, but not anything that will conflict
756
-        $class_abbreviation = isset($this->_class_abbreviations[ $class_name ])
757
-            ? $this->_class_abbreviations[ $class_name ]
756
+        $class_abbreviation = isset($this->_class_abbreviations[$class_name])
757
+            ? $this->_class_abbreviations[$class_name]
758 758
             : 'FANCY_BATMAN_PANTS';
759 759
         $class_name = str_replace('\\', '_', $class_name);
760 760
         // check if class has already been loaded, and return it if it has been
@@ -799,9 +799,9 @@  discard block
 block discarded – undo
799 799
             // convert all separators to proper DS, if no filepath, then use EE_CLASSES
800 800
             $file_path = $file_path ? str_replace(array('/', '\\'), DS, $file_path) : EE_CLASSES;
801 801
             // prep file type
802
-            $type = ! empty($type) ? trim($type, '.') . '.' : '';
802
+            $type = ! empty($type) ? trim($type, '.').'.' : '';
803 803
             // build full file path
804
-            $file_paths[$key] = rtrim($file_path, DS) . DS . $class_name . '.' . $type . 'php';
804
+            $file_paths[$key] = rtrim($file_path, DS).DS.$class_name.'.'.$type.'php';
805 805
             //does the file exist and can be read ?
806 806
             if (is_readable($file_paths[$key])) {
807 807
                 return $file_paths[$key];
@@ -832,12 +832,12 @@  discard block
 block discarded – undo
832 832
             //does the file exist and can it be read ?
833 833
             if ( ! $path) {
834 834
                 // so sorry, can't find the file
835
-                throw new EE_Error (
835
+                throw new EE_Error(
836 836
                     sprintf(
837 837
                         __('The %1$s file %2$s could not be located or is not readable due to file permissions. Please ensure that the following filepath(s) are correct: %3$s', 'event_espresso'),
838 838
                         trim($type, '.'),
839 839
                         $class_name,
840
-                        '<br />' . implode(',<br />', $file_paths)
840
+                        '<br />'.implode(',<br />', $file_paths)
841 841
                     )
842 842
                 );
843 843
             }
Please login to merge, or discard this patch.
core/libraries/messages/EE_Message_Resource_Manager.lib.php 2 patches
Indentation   +1112 added lines, -1112 removed lines patch added patch discarded remove patch
@@ -1,7 +1,7 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3 3
 if (! defined('EVENT_ESPRESSO_VERSION')) {
4
-    exit('No direct script access allowed');
4
+	exit('No direct script access allowed');
5 5
 }
6 6
 
7 7
 
@@ -17,1117 +17,1117 @@  discard block
 block discarded – undo
17 17
 class EE_Message_Resource_Manager
18 18
 {
19 19
 
20
-    /**
21
-     * This option in the database is used to keep a record of message types that have been activated for a messenger
22
-     * at some point in the history of the site.  It is utilized by the implementation of the 'force' flag in
23
-     * EE_Register_Message_Type.  The force flag is an indication of whether a message type should be activated by
24
-     * default when the message type is registered.  However, if a user has explicitly deactivated a message type, then
25
-     * the force flag is ignored.  The method by which the code knows whether to ignore this flag is via this option.
26
-     * Note, that this is NOT a historical record.  Its entirely possible for a message type to have been activated for
27
-     * a messenger and yet not have a record in this option.  This occurs when a message type is inactivated through an
28
-     * automated process (when an add-on registering the message type deactivates, or when some other code calls the
29
-     * EE_Registery_Message_Type::deregister method) and the related record(s) is(are) removed from this option to ensure
30
-     * the "force" flag is respected if that message type is later re-registered.
31
-     *
32
-     * This option should NOT be used to determine the current "active" state of a message type for a given messenger.
33
-     *
34
-     * The name of this option (and related methods/properties) is due to matching the original intended purpose for the
35
-     * option that got superseded by later behaviour requirements.
36
-     */
37
-    const HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME = 'ee_has_activated_messenger';
38
-
39
-    /**
40
-     * @type boolean $_initialized
41
-     */
42
-    protected $_initialized = false;
43
-
44
-    /**
45
-     * @type EE_Messenger_Collection $_messenger_collection_loader
46
-     */
47
-    protected $_messenger_collection_loader;
48
-
49
-    /**
50
-     * @type EE_Message_Type_Collection $_message_type_collection_loader
51
-     */
52
-    protected $_message_type_collection_loader;
53
-
54
-    /**
55
-     * @type EEM_Message_Template_Group $_message_template_group_model
56
-     */
57
-    protected $_message_template_group_model;
58
-
59
-    /**
60
-     * @type EE_messenger[]
61
-     */
62
-    protected $_installed_messengers = array();
63
-
64
-    /**
65
-     * @type EE_message_type[]
66
-     */
67
-    protected $_installed_message_types = array();
68
-
69
-    /**
70
-     * Array of active messengers.
71
-     * Format is this:
72
-     * array(
73
-     *      'messenger_name' => EE_messenger
74
-     * )
75
-     *
76
-     * @type EE_messenger[]
77
-     */
78
-    protected $_active_messengers = array();
79
-
80
-    /**
81
-     * Formatted array of active message types grouped per messenger.
82
-     * Format is this:
83
-     * array(
84
-     *      'messenger_name' => array(
85
-     *          'settings' => array(
86
-     *              '{messenger_name}-message_types' => array(
87
-     *                  'message_type_name' => array() //variable array of settings corresponding to message type.
88
-     *              )
89
-     *          )
90
-     *      )
91
-     * )
92
-     *
93
-     * @type array
94
-     */
95
-    protected $_active_message_types = array();
96
-
97
-
98
-    /**
99
-     * This holds the array of messengers and their corresponding message types that have
100
-     * been activated on a site at some point.  This is an important record that helps the messages system
101
-     * not accidentally reactivate something that was intentionally deactivated by a user.
102
-     *
103
-     * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
104
-     *
105
-     * @type array
106
-     */
107
-    protected $_has_activated_messengers_and_message_types = array();
108
-
109
-    /**
110
-     * An array of unique message type contexts across all active message types.
111
-     * The array will be indexed by either 'slugs' or 'all'.
112
-     * The slugs index contains an array indexed by unique context slugs with the latest label representation for that
113
-     * slug. array(
114
-     *      'context_slug' => 'localized label for context obtained from latest message type in the loop'.
115
-     * );
116
-     * The all index returns an array in this format:
117
-     * array(
118
-     *      'message_type_name' => array(
119
-     *          'context_slug' => array(
120
-     *              'label' => 'localized label for context',
121
-     *              'description' => 'localized description for context'
122
-     *          )
123
-     *      )
124
-     * );
125
-     *
126
-     * @type array
127
-     */
128
-    protected $_contexts = array();
129
-
130
-
131
-    /**
132
-     * EE_Message_Resource_Manager constructor.
133
-     *
134
-     * @param \EE_Messenger_Collection_Loader    $Messenger_Collection_Loader
135
-     * @param \EE_Message_Type_Collection_Loader $Message_Type_Collection_Loader
136
-     * @param \EEM_Message_Template_Group        $Message_Template_Group_Model
137
-     */
138
-    function __construct(
139
-        EE_Messenger_Collection_Loader $Messenger_Collection_Loader,
140
-        EE_Message_Type_Collection_Loader $Message_Type_Collection_Loader,
141
-        EEM_Message_Template_Group $Message_Template_Group_Model
142
-    ) {
143
-        $this->_messenger_collection_loader    = $Messenger_Collection_Loader;
144
-        $this->_message_type_collection_loader = $Message_Type_Collection_Loader;
145
-        $this->_message_template_group_model   = $Message_Template_Group_Model;
146
-    }
147
-
148
-
149
-    /**
150
-     * @return void
151
-     */
152
-    protected function _initialize_collections()
153
-    {
154
-        if ($this->_initialized) {
155
-            return;
156
-        }
157
-        $this->_initialized = true;
158
-        $this->_messenger_collection_loader->load_messengers_from_folder();
159
-        $this->_message_type_collection_loader->load_message_types_from_folder();
160
-        $this->get_has_activated_messengers_option(true);
161
-        $this->_set_active_messengers_and_message_types();
162
-    }
163
-
164
-
165
-    /**
166
-     * @return EE_Messenger_Collection
167
-     */
168
-    public function messenger_collection()
169
-    {
170
-        $this->_initialize_collections();
171
-        return $this->_messenger_collection_loader->messenger_collection();
172
-    }
173
-
174
-
175
-    /**
176
-     * @return EE_messenger[]
177
-     */
178
-    public function active_messengers()
179
-    {
180
-        $this->_initialize_collections();
181
-        return $this->_active_messengers;
182
-    }
183
-
184
-
185
-    /**
186
-     * @param string $messenger_name
187
-     * @return \EE_messenger
188
-     */
189
-    public function get_messenger($messenger_name)
190
-    {
191
-        return $this->messenger_collection()->get_by_info($messenger_name);
192
-    }
193
-
194
-
195
-    /**
196
-     * This returns the corresponding EE_messenger object for the given string if it is active.
197
-     *
198
-     * @param string $messenger
199
-     * @return EE_messenger | null
200
-     */
201
-    public function get_active_messenger($messenger)
202
-    {
203
-        $this->_initialize_collections();
204
-        return ! empty($this->_active_messengers[$messenger]) ? $this->_active_messengers[$messenger] : null;
205
-    }
206
-
207
-
208
-    /**
209
-     * @return \EE_messenger[]
210
-     */
211
-    public function installed_messengers()
212
-    {
213
-        if (empty($this->_installed_messengers)) {
214
-            $this->_installed_messengers = array();
215
-            $this->messenger_collection()->rewind();
216
-            while ($this->messenger_collection()->valid()) {
217
-                $this->_installed_messengers[$this->messenger_collection()->current()->name] = $this->messenger_collection()->current();
218
-                $this->messenger_collection()->next();
219
-            }
220
-        }
221
-        return $this->_installed_messengers;
222
-    }
223
-
224
-
225
-    /**
226
-     * @param string $messenger_name
227
-     * @return \EE_messenger
228
-     * @throws \EE_Error
229
-     */
230
-    public function valid_messenger($messenger_name)
231
-    {
232
-        $messenger = $this->get_messenger($messenger_name);
233
-        if ($messenger instanceof EE_messenger) {
234
-            return $messenger;
235
-        }
236
-        throw new EE_Error(
237
-            sprintf(
238
-                __('The "%1$s" messenger is either invalid or not installed', 'event_espresso'),
239
-                $messenger_name
240
-            )
241
-        );
242
-    }
243
-
244
-
245
-    /**
246
-     * @return EE_Message_Type_Collection
247
-     */
248
-    public function message_type_collection()
249
-    {
250
-        $this->_initialize_collections();
251
-        return $this->_message_type_collection_loader->message_type_collection();
252
-    }
253
-
254
-
255
-    /**
256
-     * @return array
257
-     */
258
-    public function active_message_types()
259
-    {
260
-        $this->_initialize_collections();
261
-        return $this->_active_message_types;
262
-    }
263
-
264
-
265
-    /**
266
-     * @param string $message_type_name
267
-     * @return \EE_message_type
268
-     */
269
-    public function get_message_type($message_type_name)
270
-    {
271
-        return $this->message_type_collection()->get_by_info($message_type_name);
272
-    }
273
-
274
-
275
-    /**
276
-     * This returns the EE_message_type from the active message types array ( if present );
277
-     *
278
-     * @param string $messenger_name
279
-     * @param string $message_type_name
280
-     * @return \EE_message_type|null
281
-     */
282
-    public function get_active_message_type_for_messenger($messenger_name, $message_type_name)
283
-    {
284
-        return $this->is_message_type_active_for_messenger($messenger_name, $message_type_name)
285
-            ? $this->get_message_type($message_type_name)
286
-            : null;
287
-    }
288
-
289
-
290
-    /**
291
-     * Returns whether the given message type is active for the given messenger.
292
-     *
293
-     * @param string $messenger_name
294
-     * @param string $message_type_name
295
-     * @return bool
296
-     */
297
-    public function is_message_type_active_for_messenger($messenger_name, $message_type_name)
298
-    {
299
-        $this->_initialize_collections();
300
-        return ! empty($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]);
301
-    }
302
-
303
-
304
-    /**
305
-     * Returns whether the given messenger is active.
306
-     *
307
-     * @param string $messenger_name the name of the messenger to check if active.
308
-     * @return bool
309
-     */
310
-    public function is_messenger_active($messenger_name)
311
-    {
312
-        $this->_initialize_collections();
313
-        return ! empty($this->_active_message_types[$messenger_name]);
314
-    }
315
-
316
-
317
-    /**
318
-     * This returns any settings that might be on a message type for a messenger
319
-     *
320
-     * @param string $messenger_name    The slug of the messenger
321
-     * @param string $message_type_name The slug of the message type getting the settings for.
322
-     * @return array
323
-     */
324
-    public function get_message_type_settings_for_messenger($messenger_name, $message_type_name)
325
-    {
326
-        $settings = array();
327
-        if ($this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
328
-            $settings = isset($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings'])
329
-                ? $this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings']
330
-                : array();
331
-        }
332
-        return $settings;
333
-    }
334
-
335
-
336
-    /**
337
-     * Returns whether the given messenger name has active message types on it.
338
-     * Infers whether the messenger is active or not as well.
339
-     *
340
-     * @param string $messenger_name
341
-     * @return bool
342
-     */
343
-    public function messenger_has_active_message_types($messenger_name)
344
-    {
345
-        $this->_initialize_collections();
346
-        return
347
-            ! empty($this->_active_message_types[$messenger_name])
348
-            && ! empty($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types']);
349
-    }
350
-
351
-
352
-    /**
353
-     * This checks the _active_message_types property for any active message types
354
-     * that are present for the given messenger and returns them.
355
-     *
356
-     * @since 4.9.0
357
-     * @param string $messenger_name The messenger being checked
358
-     * @return EE_message_type[]|array    (empty array if no active_message_types)
359
-     */
360
-    public function get_active_message_types_for_messenger($messenger_name)
361
-    {
362
-        $message_types = array();
363
-        if (! $this->messenger_has_active_message_types($messenger_name)) {
364
-            return $message_types;
365
-        }
366
-        $installed_message_types = $this->installed_message_types();
367
-        foreach ($installed_message_types as $message_type_name => $message_type) {
368
-            if ($this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
369
-                $message_types[$message_type_name] = $message_type;
370
-            }
371
-        }
372
-        return $message_types;
373
-    }
374
-
375
-
376
-    /**
377
-     * This does NOT return the _active_message_types property but
378
-     * simply returns an array of active message type names from that property.
379
-     * (The _active_message_types property is indexed by messenger and active message_types per messenger).
380
-     *
381
-     * @return array message_type references (string)
382
-     */
383
-    public function list_of_active_message_types()
384
-    {
385
-        $active_message_type_names = array();
386
-        $this->_initialize_collections();
387
-        foreach ($this->_active_message_types as $messenger => $messenger_settings) {
388
-            if (! isset($messenger_settings['settings'][$messenger . '-message_types'])) {
389
-                continue;
390
-            }
391
-            foreach ($messenger_settings['settings'][$messenger . '-message_types'] as $message_type_name => $message_type_config) {
392
-                if (! in_array($message_type_name, $active_message_type_names)) {
393
-                    $active_message_type_names[] = $message_type_name;
394
-                }
395
-            }
396
-        }
397
-        return $active_message_type_names;
398
-    }
399
-
400
-
401
-    /**
402
-     * Same as list_of_active_message_types() except this returns actual EE_message_type objects
403
-     *
404
-     * @since 4.9.0
405
-     * @return \EE_message_type[]
406
-     */
407
-    public function get_active_message_type_objects()
408
-    {
409
-        $active_message_types      = array();
410
-        $installed_message_types   = $this->installed_message_types();
411
-        $active_message_type_names = $this->list_of_active_message_types();
412
-        foreach ($active_message_type_names as $active_message_type_name) {
413
-            if (isset($installed_message_types[$active_message_type_name])) {
414
-                $active_message_types[$active_message_type_name] = $installed_message_types[$active_message_type_name];
415
-            }
416
-        }
417
-        return $active_message_types;
418
-    }
419
-
420
-
421
-    /**
422
-     * @return \EE_message_type[]
423
-     */
424
-    public function installed_message_types()
425
-    {
426
-        if (empty($this->_installed_message_types)) {
427
-            $this->message_type_collection()->rewind();
428
-            while ($this->message_type_collection()->valid()) {
429
-                $this->_installed_message_types[$this->message_type_collection()->current()->name] = $this->message_type_collection()->current();
430
-                $this->message_type_collection()->next();
431
-            }
432
-        }
433
-        return $this->_installed_message_types;
434
-    }
435
-
436
-
437
-    /**
438
-     * @param string $message_type_name
439
-     * @return \EE_message_type
440
-     * @throws \EE_Error
441
-     */
442
-    public function valid_message_type($message_type_name)
443
-    {
444
-        $message_type = $this->get_message_type($message_type_name);
445
-        if ($message_type instanceof EE_message_type) {
446
-            return $message_type;
447
-        }
448
-        throw new EE_Error(
449
-            sprintf(
450
-                __('The "%1$s" message type is either invalid or not installed', 'event_espresso'),
451
-                $message_type_name
452
-            )
453
-        );
454
-    }
455
-
456
-
457
-    /**
458
-     * valid_message_type_for_messenger
459
-     *
460
-     * @param EE_messenger $messenger
461
-     * @param string       $message_type_name
462
-     * @return boolean
463
-     * @throws \EE_Error
464
-     */
465
-    public function valid_message_type_for_messenger(EE_messenger $messenger, $message_type_name)
466
-    {
467
-        $valid_message_types = $messenger->get_valid_message_types();
468
-        if (! in_array($message_type_name, $valid_message_types)) {
469
-            throw new EE_Error(
470
-                sprintf(
471
-                    __(
472
-                        'The message type (%1$s) sent to "%2$s" is not valid for the "%3$s" messenger.  Double-check the spelling and verify that message type has been registered as a valid type with the messenger.',
473
-                        'event_espresso'
474
-                    ),
475
-                    $message_type_name,
476
-                    __METHOD__,
477
-                    $messenger->name
478
-                )
479
-            );
480
-        }
481
-        return true;
482
-    }
483
-
484
-
485
-    /**
486
-     * Used to return active messengers array stored in the wp options table.
487
-     * If no value is present in the option then an empty array is returned.
488
-     *
489
-     * @param   bool $reset     If true then we ignore whether the option is cached on the _active_message_types
490
-     *                          property and pull directly from the db.  Otherwise whatever is currently on the
491
-     *                          $_active_message_types property is pulled.
492
-     * @return array
493
-     */
494
-    public function get_active_messengers_option($reset = false)
495
-    {
496
-        if ($reset) {
497
-            $this->_active_message_types = get_option('ee_active_messengers', array());
498
-        }
499
-        return $this->_active_message_types;
500
-    }
501
-
502
-
503
-    /**
504
-     * Used to update the active messengers array stored in the wp options table.
505
-     *
506
-     * @param array $active_messenger_settings Incoming data to save.  If empty, then the internal cached property
507
-     *                                         representing this data is used.
508
-     * @return bool FALSE if not updated, TRUE if updated.
509
-     */
510
-    public function update_active_messengers_option($active_messenger_settings = array())
511
-    {
512
-        $active_messenger_settings = empty($active_messenger_settings) ? $this->_active_message_types : $active_messenger_settings;
513
-        //make sure _active_message_types is updated (this is the internal cache for the settings).
514
-        $this->_active_message_types = $active_messenger_settings;
515
-        return update_option('ee_active_messengers', $active_messenger_settings);
516
-    }
517
-
518
-
519
-    /**
520
-     * Used to return has activated message types for messengers array stored in the wp options table.
521
-     * If no value is present in the option then an empty array is returned.
522
-     * The value is cached on the $_has_activated_messengers_and_message_types property for future calls.
523
-     * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
524
-     *
525
-     * @param   bool $reset Used to indicate that any cached value should be ignored.
526
-     * @return array
527
-     */
528
-    public function get_has_activated_messengers_option($reset = false)
529
-    {
530
-        if ($reset || empty($this->_has_activated_messengers_and_message_types)) {
531
-            $this->_has_activated_messengers_and_message_types = get_option(self::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME, array());
532
-        }
533
-        return $this->_has_activated_messengers_and_message_types;
534
-    }
535
-
536
-
537
-    /**
538
-     * Used to update the has activated option in the db.
539
-     *
540
-     * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
541
-     *
542
-     * @param array $has_activated_messengers Incoming data to save.  If empty, then the internal cached property
543
-     *                                        representing this data is used.
544
-     * @return bool FALSE if not updated, TRUE if updated.
545
-     */
546
-    public function update_has_activated_messengers_option($has_activated_messengers = array())
547
-    {
548
-        //make sure the option has been retrieved from first so we don't overwrite it accidentally.
549
-        if (empty($has_activated_messengers) && empty($this->_has_activated_messengers_and_message_types)) {
550
-            $this->get_has_activated_messengers_option();
551
-        }
552
-        $has_activated_messengers = empty($has_activated_messengers)
553
-            ? $this->_has_activated_messengers_and_message_types
554
-            : $has_activated_messengers;
555
-        return update_option(self::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME, $has_activated_messengers);
556
-    }
557
-
558
-
559
-    /**
560
-     * wrapper for _set_active_messengers_and_message_types()
561
-     */
562
-    public function reset_active_messengers_and_message_types()
563
-    {
564
-        $this->_set_active_messengers_and_message_types();
565
-    }
566
-
567
-
568
-    /**
569
-     * Generate list of active messengers and message types from collection.
570
-     * This sets up the active messengers from what is present in the database.
571
-     */
572
-    protected function _set_active_messengers_and_message_types()
573
-    {
574
-        //echo "\n\n " . __LINE__ . ") " . __METHOD__ . "() \n";
575
-        // list of activated messengers as set via the admin
576
-        // note calling `get_active_messengers_options` also initializes the _active_message_types property.
577
-        $this->get_active_messengers_option(true);
578
-        $this->ensure_messengers_are_active(array(), false, true);
579
-        $this->update_active_messengers_option();
580
-        $this->update_has_activated_messengers_option();
581
-    }
582
-
583
-
584
-    /**
585
-     * Ensures that the specified messenger is currently active.
586
-     * If not, activates it and its default message types.
587
-     *
588
-     * @param string $messenger_name
589
-     * @param bool   $update_option Whether to update the option in the db or not.
590
-     * @return boolean true if either already active or successfully activated.
591
-     */
592
-    public function ensure_messenger_is_active($messenger_name, $update_option = true)
593
-    {
594
-        if (! isset($this->_active_messengers[$messenger_name])) {
595
-            try {
596
-                $this->activate_messenger($messenger_name, array(), $update_option);
597
-            } catch (EE_Error $e) {
598
-                EE_Error::add_error(
599
-                    $e->getMessage(),
600
-                    __FILE__,
601
-                    __FUNCTION__,
602
-                    __LINE__
603
-                );
604
-                return false;
605
-            }
606
-        }
607
-        return true;
608
-    }
609
-
610
-
611
-    /**
612
-     * This ensures the given array of messenger names is active in the system.
613
-     * Note, this method will not activate any NEW message types for the messenger when it is called. Instead,
614
-     * it will automatically activate the default message types for the messenger if its not active.
615
-     *
616
-     * @param array $messenger_names  Array of messenger names for messengers to be activated.  If an empty array
617
-     *                                (default) then will attempt to set the active messengers from the
618
-     *                                activated_messengers option
619
-     *                                (stored in $_active_message_types property).
620
-     * @param bool  $update_option    Whether to update the related active messengers option.
621
-     * @param bool  $verify           Whether to verify the messengers are installed before activating. Note if this is
622
-     *                                set to true and a messenger is indicated as active, but is NOT installed, then it
623
-     *                                will automatically be deactivated.
624
-     */
625
-    public function ensure_messengers_are_active($messenger_names = array(), $update_option = true, $verify = false)
626
-    {
627
-        $messenger_names = empty($messenger_names) ? array_keys($this->_active_message_types) : $messenger_names;
628
-
629
-        $not_installed = array();
630
-        foreach ($messenger_names as $messenger_name) {
631
-            if ($verify && ! $this->messenger_collection()->has_by_name($messenger_name)) {
632
-                $not_installed[] = $messenger_name;
633
-                $this->deactivate_messenger($messenger_name);
634
-                continue;
635
-            }
636
-            $this->ensure_messenger_is_active($messenger_name, $update_option);
637
-        }
638
-
639
-        if (! empty($not_installed)) {
640
-            EE_Error::add_error(
641
-                sprintf(
642
-                    __('The following messengers are either not installed or are invalid:%1$s %2$s', 'event_espresso'),
643
-                    '<br />',
644
-                    implode(', ', $not_installed)
645
-                ),
646
-                __FILE__, __FUNCTION__, __LINE__
647
-            );
648
-        }
649
-    }
650
-
651
-
652
-    /**
653
-     * Ensures that the specified message type for the given messenger is currently active, if not activates it.
654
-     * This ALSO ensures that the given messenger is active as well!
655
-     *
656
-     * @param string $message_type_name message type name.
657
-     * @param        $messenger_name
658
-     * @param bool   $update_option     Whether to update the option in the db or not.
659
-     * @return bool  Returns true if already is active or if was activated successfully.
660
-     * @throws \EE_Error
661
-     */
662
-    public function ensure_message_type_is_active($message_type_name, $messenger_name, $update_option = true)
663
-    {
664
-        // grab the messenger to work with.
665
-        $messenger = $this->valid_messenger($messenger_name);
666
-        if ($this->valid_message_type_for_messenger($messenger, $message_type_name)) {
667
-            //ensure messenger is active (that's an inherent coupling between active message types and the
668
-            //messenger they are being activated for.
669
-            try {
670
-                if (! $this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
671
-                    //all is good so let's just get it active
672
-                    $this->activate_messenger($messenger_name, array($message_type_name), $update_option);
673
-                }
674
-            } catch (EE_Error $e) {
675
-                EE_Error::add_error(
676
-                    $e->getMessage(),
677
-                    __FILE__,
678
-                    __FUNCTION__,
679
-                    __LINE__
680
-                );
681
-                return false;
682
-            }
683
-        }
684
-        return true;
685
-    }
686
-
687
-
688
-    /**
689
-     * This is a wrapper for `ensure_message_type_is_active` that will handle ensuring multiple message types for a
690
-     * messenger are active in one go.
691
-     *
692
-     * @param array  $message_type_names Array of message type names to ensure are active.
693
-     * @param string $messenger_name     The name of the messenger that the message types are to be activated on.
694
-     * @param bool   $update_option      Whether to persist the activation to the database or not (default true).
695
-     */
696
-    public function ensure_message_types_are_active($message_type_names, $messenger_name, $update_option = true)
697
-    {
698
-        $message_type_names = (array)$message_type_names;
699
-        foreach ($message_type_names as $message_type_name) {
700
-            // note, intentionally not updating option here because we're in a loop.
701
-            // We'll follow the instructions of the incoming $update_option argument after the loop.
702
-            $this->ensure_message_type_is_active($message_type_name, $messenger_name, false);
703
-        }
704
-        if ($update_option) {
705
-            $this->update_active_messengers_option();
706
-            $this->update_has_activated_messengers_option();
707
-        }
708
-    }
709
-
710
-
711
-    /**
712
-     * Activates the specified messenger.
713
-     *
714
-     * @param string $messenger_name
715
-     * @param array  $message_type_names        An array of message type names to activate with this messenger.
716
-     *                                          If included we do NOT setup the default message types
717
-     *                                          (assuming they are already setup.)
718
-     * @param bool   $update_active_messengers_option
719
-     * @return array of generated templates
720
-     * @throws \EE_Error
721
-     */
722
-    public function activate_messenger(
723
-        $messenger_name,
724
-        $message_type_names = array(),
725
-        $update_active_messengers_option = true
726
-    ) {
727
-        $templates = array();
728
-        // grab the messenger to work with.
729
-        $messenger = $this->messenger_collection()->get_by_info($messenger_name);
730
-        // it's inactive. Activate it.
731
-        if ($messenger instanceof EE_messenger) {
732
-            $this->_active_messengers[$messenger->name] = $messenger;
733
-            //activate incoming message types set to be activated with messenger.
734
-            $message_type_names = $this->_activate_message_types($messenger, $message_type_names);
735
-            // setup any initial settings for the messenger if necessary.
736
-            $this->add_settings_for_messenger($messenger->name);
737
-            if ($update_active_messengers_option) {
738
-                $this->update_active_messengers_option();
739
-                $this->update_has_activated_messengers_option();
740
-            }
741
-            //generate new templates if necessary and ensure all related templates that are already in the database are
742
-            //marked active.  Note, this will also deactivate a message type for a messenger if the template
743
-            //cannot be successfully created during its attempt (only happens for global template attempts).
744
-            if (! empty($message_type_names)) {
745
-                $templates = EEH_MSG_Template::generate_new_templates($messenger->name, $message_type_names, 0, true);
746
-                EEH_MSG_Template::update_to_active(array($messenger->name), $message_type_names);
747
-            }
748
-        }
749
-        return $templates;
750
-    }
751
-
752
-
753
-    /**
754
-     * Activates given message types for the given EE_messenger object.
755
-     * Note: (very important) This method does not persist the activation to the database.
756
-     * See code implementing this method in this class for examples of how to persist.
757
-     *
758
-     * @param \EE_messenger $messenger
759
-     * @param  array        $message_type_names
760
-     * @return array
761
-     */
762
-    protected function _activate_message_types(EE_messenger $messenger, $message_type_names = array())
763
-    {
764
-        //If $message_type_names is empty, AND $this->_active_message_types is empty, then that means
765
-        //things have never been initialized (which should happen on EEH_Activation::generate_message_templates).
766
-        //So ONLY then do we need to actually grab defaults and cycle through them.  Otherwise we
767
-        //only override _active_message_types when an explicit array of $message_type_names has been provided.
768
-        $message_type_names = empty($message_type_names) && ! isset($this->_active_message_types[$messenger->name])
769
-            ? $messenger->get_default_message_types()
770
-            : (array)$message_type_names;
771
-
772
-        //now we ALWAYS need to make sure that the messenger is active for the message types we're activating!
773
-        if (! isset($this->_active_message_types[$messenger->name])) {
774
-            $this->_active_message_types[$messenger->name]['settings'] = array();
775
-        }
776
-
777
-        if ($message_type_names) {
778
-            // cycle thru message types
779
-            foreach ($message_type_names as $message_type_name) {
780
-                //only register the message type as active IF it isn't already active
781
-                //and if its actually installed.
782
-                if (
783
-                ! $this->is_message_type_active_for_messenger($messenger->name, $message_type_name)
784
-                ) {
785
-                    $this->add_settings_for_message_type($messenger->name, $message_type_name);
786
-                    $this->_set_messenger_has_activated_message_type(
787
-                        $messenger,
788
-                        $message_type_name
789
-                    );
790
-                }
791
-            }
792
-        }
793
-        return $message_type_names;
794
-    }
795
-
796
-
797
-    /**
798
-     * add_settings_for_message_type
799
-     * NOTE This does NOT automatically persist any settings to the db.  Client code should call
800
-     * $this->update_active_messengers_option to persist.
801
-     *
802
-     * @param  string $messenger_name    The name of the messenger adding the settings for
803
-     * @param  string $message_type_name The name of the message type adding the settings for
804
-     * @param  array  $new_settings      Any new settings being set for the message type and messenger
805
-     */
806
-    public function add_settings_for_message_type($messenger_name, $message_type_name, $new_settings = array())
807
-    {
808
-        // get installed message type from collection
809
-        $message_type      = $this->message_type_collection()->get_by_info($message_type_name);
810
-        $existing_settings = $this->get_message_type_settings_for_messenger($messenger_name, $message_type_name);
811
-        //we need to setup any initial settings for message types
812
-        if ($message_type instanceof EE_message_type) {
813
-            $default_settings = $message_type->get_admin_settings_fields();
814
-            foreach ($default_settings as $field => $values) {
815
-                if (isset($new_settings[$field])) {
816
-                    $existing_settings[$field] = $new_settings[$field];
817
-                    continue;
818
-                }
819
-                if (! isset($existing_settings[$field])) {
820
-                    $existing_settings[$field] = $values['default'];
821
-                }
822
-            }
823
-        }
824
-        $this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings'] = $existing_settings;
825
-    }
826
-
827
-
828
-    /**
829
-     * Updates the internal cached _has_activated_messengers_and_message_types property with the given messenger
830
-     * and message type.
831
-     *
832
-     * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
833
-     *
834
-     * @access protected
835
-     * @param \EE_messenger $messenger
836
-     * @param string        $message_type_name
837
-     */
838
-    protected function _set_messenger_has_activated_message_type(EE_messenger $messenger, $message_type_name)
839
-    {
840
-
841
-        //if _has_activated_messengers_and_message_types is empty then lets ensure its initialized
842
-        if (empty($this->_has_activated_messengers_and_message_types)) {
843
-            $this->get_has_activated_messengers_option();
844
-        }
845
-
846
-        // make sure this messenger has a record in the has_activated array
847
-        if (! isset($this->_has_activated_messengers_and_message_types[$messenger->name])) {
848
-            $this->_has_activated_messengers_and_message_types[$messenger->name] = array();
849
-        }
850
-        // check if message type has already been added
851
-        if (! in_array($message_type_name, $this->_has_activated_messengers_and_message_types[$messenger->name])) {
852
-            $this->_has_activated_messengers_and_message_types[$messenger->name][] = $message_type_name;
853
-        }
854
-    }
855
-
856
-
857
-    /**
858
-     * add_settings_for_messenger
859
-     * NOTE This does NOT automatically persist any settings to the db.  Client code should call
860
-     * $this->update_active_messengers_option to persist.
861
-     *
862
-     * @param string $messenger_name The name of the messenger the settings is being added for.
863
-     * @param array  $new_settings   An array of settings to update the existing settings.
864
-     */
865
-    public function add_settings_for_messenger($messenger_name, $new_settings = array())
866
-    {
867
-        $messenger = $this->get_messenger($messenger_name);
868
-        if ($messenger instanceof EE_messenger) {
869
-            $msgr_settings = $messenger->get_admin_settings_fields();
870
-            if (! empty($msgr_settings)) {
871
-                foreach ($msgr_settings as $field => $value) {
872
-                    //is there a new setting for this?
873
-                    if (isset($new_settings[$field])) {
874
-                        $this->_active_message_types[$messenger->name]['settings'][$field] = $new_settings[$field];
875
-                        continue;
876
-                    }
877
-                    //only set the default if it isn't already set.
878
-                    if (! isset($this->_active_message_types[$messenger->name]['settings'][$field])) {
879
-                        $this->_active_message_types[$messenger->name]['settings'][$field] = $value;
880
-                    }
881
-                }
882
-            }
883
-        }
884
-    }
885
-
886
-
887
-    /**
888
-     * deactivate_messenger
889
-     *
890
-     * @param  string|EE_messenger $messenger_name name of messenger
891
-     * @return void
892
-     */
893
-    public function deactivate_messenger($messenger_name)
894
-    {
895
-        $this->_initialize_collections();
896
-        if ($messenger_name instanceof EE_messenger) {
897
-            $messenger_name = $messenger_name->name;
898
-        }
899
-        unset($this->_active_messengers[$messenger_name]);
900
-        unset($this->_active_message_types[$messenger_name]);
901
-        $this->_message_template_group_model->deactivate_message_template_groups_for($messenger_name);
902
-        $this->update_active_messengers_option();
903
-    }
904
-
905
-
906
-    /**
907
-     * Deactivates a message type (note this will deactivate across all messenger's it is active on.
908
-     *
909
-     * @param  string $message_type_name     name of message type being deactivated
910
-     * @param bool    $set_has_active_record By default we always record the has_active record when deactivating a message
911
-     *                                       type.  However, this can be overridden if we don't want this set (usually when
912
-     *                                       this is called as a part of deregistration of a custom message type)
913
-     */
914
-    public function deactivate_message_type($message_type_name, $set_has_active_record = true)
915
-    {
916
-        $this->_initialize_collections();
917
-        if ($message_type_name instanceof EE_message_type) {
918
-            $message_type_name = $message_type_name->name;
919
-        }
920
-        foreach ($this->_active_message_types as $messenger_name => $settings) {
921
-            unset(
922
-                $this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]
923
-            );
924
-
925
-            //we always record (even on deactivation) that a message type has been activated because there should at
926
-            //least be a record in the "has_activated" option that it WAS active at one point.
927
-            if ($set_has_active_record) {
928
-                $messenger = $this->get_messenger($messenger_name);
929
-                $this->_set_messenger_has_activated_message_type($messenger, $message_type_name);
930
-            }
931
-        }
932
-        $this->_message_template_group_model->deactivate_message_template_groups_for('', $message_type_name);
933
-        $this->update_active_messengers_option();
934
-        $this->update_has_activated_messengers_option();
935
-    }
936
-
937
-
938
-    /**
939
-     * Deactivates a message type for a specific messenger as opposed to all messengers.
940
-     *
941
-     * @param string $message_type_name Name of message type being deactivated.
942
-     * @param string $messenger_name    Name of messenger the message type is being deactivated for.
943
-     */
944
-    public function deactivate_message_type_for_messenger($message_type_name, $messenger_name)
945
-    {
946
-        $this->_initialize_collections();
947
-        if ($this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
948
-            unset($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]);
949
-        }
950
-        $this->_message_template_group_model->deactivate_message_template_groups_for(array($messenger_name),
951
-            array($message_type_name));
952
-        $this->update_active_messengers_option();
953
-    }
954
-
955
-
956
-    /**
957
-     * Used to verify if a message can be sent for the given messenger and message type
958
-     * and that it is a generating messenger (used for generating message templates).
959
-     *
960
-     * @param EE_messenger    $messenger    messenger used in trigger
961
-     * @param EE_message_type $message_type message type used in trigger
962
-     * @return bool true is a generating messenger and can be sent OR FALSE meaning cannot send.
963
-     */
964
-    public function is_generating_messenger_and_active(EE_messenger $messenger, EE_message_type $message_type)
965
-    {
966
-        //get the $messengers the message type says it can be used with.
967
-        foreach ($message_type->with_messengers() as $generating_messenger => $secondary_messengers) {
968
-            if (
969
-                $messenger->name === $generating_messenger
970
-                && $this->is_message_type_active_for_messenger($messenger->name, $message_type->name)
971
-            ) {
972
-                return true;
973
-            }
974
-        }
975
-        return false;
976
-    }
977
-
978
-
979
-    /**
980
-     * This returns all the contexts that are registered by all message types.
981
-     * If $slugs_only is true,
982
-     * then just an array indexed by unique context slugs with the latest label representation for that slug.
983
-     * array(
984
-     *      'context_slug' => 'localized label for context obtained from latest message type in the loop'.
985
-     * );
986
-     * If $slugs_only is false, then the format is:
987
-     * array(
988
-     *      'message_type_name' => array(
989
-     *          'context_slug' => array(
990
-     *              'label' => 'localized label for context',
991
-     *              'description' => 'localized description for context'
992
-     *          )
993
-     *      )
994
-     * );
995
-     * Keep in mind that although different message types may share the same context slugs,
996
-     * it is possible that the context is described differently by the message type.
997
-     *
998
-     * @since 4.9.0
999
-     * @param   bool $slugs_only Whether to return an array of just slugs and labels (true)
1000
-     *                           or all contexts indexed by message type.
1001
-     * @return array
1002
-     */
1003
-    public function get_all_contexts($slugs_only = true)
1004
-    {
1005
-        $key = $slugs_only ? 'slugs' : 'all';
1006
-        // check if contexts has been setup yet.
1007
-        if (empty($this->_contexts[$key])) {
1008
-            // So let's get all active message type objects and loop through to get all unique contexts
1009
-            foreach ($this->get_active_message_type_objects() as $message_type) {
1010
-                if ($message_type instanceof EE_message_type) {
1011
-                    $message_type_contexts = $message_type->get_contexts();
1012
-                    if ($slugs_only) {
1013
-                        foreach ($message_type_contexts as $context => $context_details) {
1014
-                            $this->_contexts[$key][$context] = $context_details['label'];
1015
-                        }
1016
-                    } else {
1017
-                        $this->_contexts[$key][$message_type->name] = $message_type_contexts;
1018
-                    }
1019
-                }
1020
-            }
1021
-        }
1022
-        return ! empty($this->_contexts[$key]) ? $this->_contexts[$key] : array();
1023
-    }
1024
-
1025
-
1026
-    /**
1027
-     * This checks the internal record of what message types are considered "active" and verifies that
1028
-     * there is an installed class definition for that message type.  If the active message type does not have a
1029
-     * corresponding accessible message type class then it will be deactivated from all messengers it is active on and
1030
-     * any related message templates will be inactivated as well.
1031
-     *
1032
-     * @return bool   true means all active message types are valid, false means at least one message type was
1033
-     *                deactivated.
1034
-     */
1035
-    public function validate_active_message_types_are_installed()
1036
-    {
1037
-        $list_of_active_message_type_names = $this->list_of_active_message_types();
1038
-        $installed_message_types           = $this->installed_message_types();
1039
-        $all_message_types_valid           = true;
1040
-        //loop through list of active message types and verify they are installed.
1041
-        foreach ($list_of_active_message_type_names as $message_type_name) {
1042
-            if (! isset($installed_message_types[$message_type_name])) {
1043
-                $this->remove_message_type_has_been_activated_from_all_messengers(
1044
-                    $message_type_name,
1045
-                    true
1046
-                );
1047
-                $this->deactivate_message_type($message_type_name, false);
1048
-                $all_message_types_valid = false;
1049
-            }
1050
-        }
1051
-        return $all_message_types_valid;
1052
-    }
1053
-
1054
-
1055
-    /**
1056
-     * This method checks the `ee_has_activated_messenger` option to see if the message type has ever been
1057
-     * activated for the given messenger.  This can be called by client code on plugin updates etc to determine whether
1058
-     * to attempt automatically reactivating message types that should be activated by default or not.
1059
-     *
1060
-     * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
1061
-     *
1062
-     * @param $message_type_name
1063
-     * @param $messenger_name
1064
-     * @return bool
1065
-     */
1066
-    public function has_message_type_been_activated_for_messenger($message_type_name, $messenger_name)
1067
-    {
1068
-        $has_activated = $this->get_has_activated_messengers_option();
1069
-        return isset($has_activated[$messenger_name])
1070
-               && in_array($message_type_name, $has_activated[$messenger_name]);
1071
-    }
1072
-
1073
-
1074
-    /**
1075
-     * This method unsets a message type from the given messenger has activated option.
1076
-     *
1077
-     * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
1078
-     *
1079
-     * @param string $message_type_name
1080
-     * @param string $messenger_name
1081
-     * @param bool   $consider_current_state  Whether to consider whether the  message type is currently active or not.
1082
-     *                                        If it is currently active, then remove.  Otherwise leave it alone.
1083
-     */
1084
-    public function remove_message_type_has_been_activated_for_messenger(
1085
-        $message_type_name,
1086
-        $messenger_name,
1087
-        $consider_current_state = false
1088
-    ) {
1089
-        if ($consider_current_state
1090
-            && ! $this->is_message_type_active_for_messenger($messenger_name, $message_type_name)
1091
-        ) {
1092
-            //when consider current state is true, this means we don't want to change anything on the "has_activated"
1093
-            //record if the message type is currently active for this messenger.  This is used when we want to retain
1094
-            //the record for user initiated inactivations of the message type.
1095
-            return;
1096
-        }
1097
-        $has_activated = $this->get_has_activated_messengers_option();
1098
-        $key_for_message_type = isset($has_activated[$messenger_name])
1099
-            ? array_search($message_type_name, $has_activated[$messenger_name], true)
1100
-            : false;
1101
-        if ($key_for_message_type !== false) {
1102
-            unset($has_activated[$messenger_name][$key_for_message_type]);
1103
-            $this->update_has_activated_messengers_option($has_activated);
1104
-            //reset the internal cached property
1105
-            $this->get_has_activated_messengers_option(true);
1106
-        }
1107
-    }
1108
-
1109
-
1110
-    /**
1111
-     * Removes a message type active record from all messengers it is attached to.
1112
-     *
1113
-     * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
1114
-     *
1115
-     * @param      $message_type_name
1116
-     * @param bool $consider_current_state  Whether to consider whether the  message type is currently active or not.
1117
-     *                                      If it is currently active, then remove.  Otherwise leave it alone.
1118
-     */
1119
-    public function remove_message_type_has_been_activated_from_all_messengers(
1120
-        $message_type_name,
1121
-        $consider_current_state = false
1122
-    ) {
1123
-        foreach(array_keys($this->get_has_activated_messengers_option()) as $messenger_name) {
1124
-            $this->remove_message_type_has_been_activated_for_messenger(
1125
-                $message_type_name,
1126
-                $messenger_name,
1127
-                $consider_current_state
1128
-            );
1129
-        }
1130
-    }
20
+	/**
21
+	 * This option in the database is used to keep a record of message types that have been activated for a messenger
22
+	 * at some point in the history of the site.  It is utilized by the implementation of the 'force' flag in
23
+	 * EE_Register_Message_Type.  The force flag is an indication of whether a message type should be activated by
24
+	 * default when the message type is registered.  However, if a user has explicitly deactivated a message type, then
25
+	 * the force flag is ignored.  The method by which the code knows whether to ignore this flag is via this option.
26
+	 * Note, that this is NOT a historical record.  Its entirely possible for a message type to have been activated for
27
+	 * a messenger and yet not have a record in this option.  This occurs when a message type is inactivated through an
28
+	 * automated process (when an add-on registering the message type deactivates, or when some other code calls the
29
+	 * EE_Registery_Message_Type::deregister method) and the related record(s) is(are) removed from this option to ensure
30
+	 * the "force" flag is respected if that message type is later re-registered.
31
+	 *
32
+	 * This option should NOT be used to determine the current "active" state of a message type for a given messenger.
33
+	 *
34
+	 * The name of this option (and related methods/properties) is due to matching the original intended purpose for the
35
+	 * option that got superseded by later behaviour requirements.
36
+	 */
37
+	const HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME = 'ee_has_activated_messenger';
38
+
39
+	/**
40
+	 * @type boolean $_initialized
41
+	 */
42
+	protected $_initialized = false;
43
+
44
+	/**
45
+	 * @type EE_Messenger_Collection $_messenger_collection_loader
46
+	 */
47
+	protected $_messenger_collection_loader;
48
+
49
+	/**
50
+	 * @type EE_Message_Type_Collection $_message_type_collection_loader
51
+	 */
52
+	protected $_message_type_collection_loader;
53
+
54
+	/**
55
+	 * @type EEM_Message_Template_Group $_message_template_group_model
56
+	 */
57
+	protected $_message_template_group_model;
58
+
59
+	/**
60
+	 * @type EE_messenger[]
61
+	 */
62
+	protected $_installed_messengers = array();
63
+
64
+	/**
65
+	 * @type EE_message_type[]
66
+	 */
67
+	protected $_installed_message_types = array();
68
+
69
+	/**
70
+	 * Array of active messengers.
71
+	 * Format is this:
72
+	 * array(
73
+	 *      'messenger_name' => EE_messenger
74
+	 * )
75
+	 *
76
+	 * @type EE_messenger[]
77
+	 */
78
+	protected $_active_messengers = array();
79
+
80
+	/**
81
+	 * Formatted array of active message types grouped per messenger.
82
+	 * Format is this:
83
+	 * array(
84
+	 *      'messenger_name' => array(
85
+	 *          'settings' => array(
86
+	 *              '{messenger_name}-message_types' => array(
87
+	 *                  'message_type_name' => array() //variable array of settings corresponding to message type.
88
+	 *              )
89
+	 *          )
90
+	 *      )
91
+	 * )
92
+	 *
93
+	 * @type array
94
+	 */
95
+	protected $_active_message_types = array();
96
+
97
+
98
+	/**
99
+	 * This holds the array of messengers and their corresponding message types that have
100
+	 * been activated on a site at some point.  This is an important record that helps the messages system
101
+	 * not accidentally reactivate something that was intentionally deactivated by a user.
102
+	 *
103
+	 * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
104
+	 *
105
+	 * @type array
106
+	 */
107
+	protected $_has_activated_messengers_and_message_types = array();
108
+
109
+	/**
110
+	 * An array of unique message type contexts across all active message types.
111
+	 * The array will be indexed by either 'slugs' or 'all'.
112
+	 * The slugs index contains an array indexed by unique context slugs with the latest label representation for that
113
+	 * slug. array(
114
+	 *      'context_slug' => 'localized label for context obtained from latest message type in the loop'.
115
+	 * );
116
+	 * The all index returns an array in this format:
117
+	 * array(
118
+	 *      'message_type_name' => array(
119
+	 *          'context_slug' => array(
120
+	 *              'label' => 'localized label for context',
121
+	 *              'description' => 'localized description for context'
122
+	 *          )
123
+	 *      )
124
+	 * );
125
+	 *
126
+	 * @type array
127
+	 */
128
+	protected $_contexts = array();
129
+
130
+
131
+	/**
132
+	 * EE_Message_Resource_Manager constructor.
133
+	 *
134
+	 * @param \EE_Messenger_Collection_Loader    $Messenger_Collection_Loader
135
+	 * @param \EE_Message_Type_Collection_Loader $Message_Type_Collection_Loader
136
+	 * @param \EEM_Message_Template_Group        $Message_Template_Group_Model
137
+	 */
138
+	function __construct(
139
+		EE_Messenger_Collection_Loader $Messenger_Collection_Loader,
140
+		EE_Message_Type_Collection_Loader $Message_Type_Collection_Loader,
141
+		EEM_Message_Template_Group $Message_Template_Group_Model
142
+	) {
143
+		$this->_messenger_collection_loader    = $Messenger_Collection_Loader;
144
+		$this->_message_type_collection_loader = $Message_Type_Collection_Loader;
145
+		$this->_message_template_group_model   = $Message_Template_Group_Model;
146
+	}
147
+
148
+
149
+	/**
150
+	 * @return void
151
+	 */
152
+	protected function _initialize_collections()
153
+	{
154
+		if ($this->_initialized) {
155
+			return;
156
+		}
157
+		$this->_initialized = true;
158
+		$this->_messenger_collection_loader->load_messengers_from_folder();
159
+		$this->_message_type_collection_loader->load_message_types_from_folder();
160
+		$this->get_has_activated_messengers_option(true);
161
+		$this->_set_active_messengers_and_message_types();
162
+	}
163
+
164
+
165
+	/**
166
+	 * @return EE_Messenger_Collection
167
+	 */
168
+	public function messenger_collection()
169
+	{
170
+		$this->_initialize_collections();
171
+		return $this->_messenger_collection_loader->messenger_collection();
172
+	}
173
+
174
+
175
+	/**
176
+	 * @return EE_messenger[]
177
+	 */
178
+	public function active_messengers()
179
+	{
180
+		$this->_initialize_collections();
181
+		return $this->_active_messengers;
182
+	}
183
+
184
+
185
+	/**
186
+	 * @param string $messenger_name
187
+	 * @return \EE_messenger
188
+	 */
189
+	public function get_messenger($messenger_name)
190
+	{
191
+		return $this->messenger_collection()->get_by_info($messenger_name);
192
+	}
193
+
194
+
195
+	/**
196
+	 * This returns the corresponding EE_messenger object for the given string if it is active.
197
+	 *
198
+	 * @param string $messenger
199
+	 * @return EE_messenger | null
200
+	 */
201
+	public function get_active_messenger($messenger)
202
+	{
203
+		$this->_initialize_collections();
204
+		return ! empty($this->_active_messengers[$messenger]) ? $this->_active_messengers[$messenger] : null;
205
+	}
206
+
207
+
208
+	/**
209
+	 * @return \EE_messenger[]
210
+	 */
211
+	public function installed_messengers()
212
+	{
213
+		if (empty($this->_installed_messengers)) {
214
+			$this->_installed_messengers = array();
215
+			$this->messenger_collection()->rewind();
216
+			while ($this->messenger_collection()->valid()) {
217
+				$this->_installed_messengers[$this->messenger_collection()->current()->name] = $this->messenger_collection()->current();
218
+				$this->messenger_collection()->next();
219
+			}
220
+		}
221
+		return $this->_installed_messengers;
222
+	}
223
+
224
+
225
+	/**
226
+	 * @param string $messenger_name
227
+	 * @return \EE_messenger
228
+	 * @throws \EE_Error
229
+	 */
230
+	public function valid_messenger($messenger_name)
231
+	{
232
+		$messenger = $this->get_messenger($messenger_name);
233
+		if ($messenger instanceof EE_messenger) {
234
+			return $messenger;
235
+		}
236
+		throw new EE_Error(
237
+			sprintf(
238
+				__('The "%1$s" messenger is either invalid or not installed', 'event_espresso'),
239
+				$messenger_name
240
+			)
241
+		);
242
+	}
243
+
244
+
245
+	/**
246
+	 * @return EE_Message_Type_Collection
247
+	 */
248
+	public function message_type_collection()
249
+	{
250
+		$this->_initialize_collections();
251
+		return $this->_message_type_collection_loader->message_type_collection();
252
+	}
253
+
254
+
255
+	/**
256
+	 * @return array
257
+	 */
258
+	public function active_message_types()
259
+	{
260
+		$this->_initialize_collections();
261
+		return $this->_active_message_types;
262
+	}
263
+
264
+
265
+	/**
266
+	 * @param string $message_type_name
267
+	 * @return \EE_message_type
268
+	 */
269
+	public function get_message_type($message_type_name)
270
+	{
271
+		return $this->message_type_collection()->get_by_info($message_type_name);
272
+	}
273
+
274
+
275
+	/**
276
+	 * This returns the EE_message_type from the active message types array ( if present );
277
+	 *
278
+	 * @param string $messenger_name
279
+	 * @param string $message_type_name
280
+	 * @return \EE_message_type|null
281
+	 */
282
+	public function get_active_message_type_for_messenger($messenger_name, $message_type_name)
283
+	{
284
+		return $this->is_message_type_active_for_messenger($messenger_name, $message_type_name)
285
+			? $this->get_message_type($message_type_name)
286
+			: null;
287
+	}
288
+
289
+
290
+	/**
291
+	 * Returns whether the given message type is active for the given messenger.
292
+	 *
293
+	 * @param string $messenger_name
294
+	 * @param string $message_type_name
295
+	 * @return bool
296
+	 */
297
+	public function is_message_type_active_for_messenger($messenger_name, $message_type_name)
298
+	{
299
+		$this->_initialize_collections();
300
+		return ! empty($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]);
301
+	}
302
+
303
+
304
+	/**
305
+	 * Returns whether the given messenger is active.
306
+	 *
307
+	 * @param string $messenger_name the name of the messenger to check if active.
308
+	 * @return bool
309
+	 */
310
+	public function is_messenger_active($messenger_name)
311
+	{
312
+		$this->_initialize_collections();
313
+		return ! empty($this->_active_message_types[$messenger_name]);
314
+	}
315
+
316
+
317
+	/**
318
+	 * This returns any settings that might be on a message type for a messenger
319
+	 *
320
+	 * @param string $messenger_name    The slug of the messenger
321
+	 * @param string $message_type_name The slug of the message type getting the settings for.
322
+	 * @return array
323
+	 */
324
+	public function get_message_type_settings_for_messenger($messenger_name, $message_type_name)
325
+	{
326
+		$settings = array();
327
+		if ($this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
328
+			$settings = isset($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings'])
329
+				? $this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings']
330
+				: array();
331
+		}
332
+		return $settings;
333
+	}
334
+
335
+
336
+	/**
337
+	 * Returns whether the given messenger name has active message types on it.
338
+	 * Infers whether the messenger is active or not as well.
339
+	 *
340
+	 * @param string $messenger_name
341
+	 * @return bool
342
+	 */
343
+	public function messenger_has_active_message_types($messenger_name)
344
+	{
345
+		$this->_initialize_collections();
346
+		return
347
+			! empty($this->_active_message_types[$messenger_name])
348
+			&& ! empty($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types']);
349
+	}
350
+
351
+
352
+	/**
353
+	 * This checks the _active_message_types property for any active message types
354
+	 * that are present for the given messenger and returns them.
355
+	 *
356
+	 * @since 4.9.0
357
+	 * @param string $messenger_name The messenger being checked
358
+	 * @return EE_message_type[]|array    (empty array if no active_message_types)
359
+	 */
360
+	public function get_active_message_types_for_messenger($messenger_name)
361
+	{
362
+		$message_types = array();
363
+		if (! $this->messenger_has_active_message_types($messenger_name)) {
364
+			return $message_types;
365
+		}
366
+		$installed_message_types = $this->installed_message_types();
367
+		foreach ($installed_message_types as $message_type_name => $message_type) {
368
+			if ($this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
369
+				$message_types[$message_type_name] = $message_type;
370
+			}
371
+		}
372
+		return $message_types;
373
+	}
374
+
375
+
376
+	/**
377
+	 * This does NOT return the _active_message_types property but
378
+	 * simply returns an array of active message type names from that property.
379
+	 * (The _active_message_types property is indexed by messenger and active message_types per messenger).
380
+	 *
381
+	 * @return array message_type references (string)
382
+	 */
383
+	public function list_of_active_message_types()
384
+	{
385
+		$active_message_type_names = array();
386
+		$this->_initialize_collections();
387
+		foreach ($this->_active_message_types as $messenger => $messenger_settings) {
388
+			if (! isset($messenger_settings['settings'][$messenger . '-message_types'])) {
389
+				continue;
390
+			}
391
+			foreach ($messenger_settings['settings'][$messenger . '-message_types'] as $message_type_name => $message_type_config) {
392
+				if (! in_array($message_type_name, $active_message_type_names)) {
393
+					$active_message_type_names[] = $message_type_name;
394
+				}
395
+			}
396
+		}
397
+		return $active_message_type_names;
398
+	}
399
+
400
+
401
+	/**
402
+	 * Same as list_of_active_message_types() except this returns actual EE_message_type objects
403
+	 *
404
+	 * @since 4.9.0
405
+	 * @return \EE_message_type[]
406
+	 */
407
+	public function get_active_message_type_objects()
408
+	{
409
+		$active_message_types      = array();
410
+		$installed_message_types   = $this->installed_message_types();
411
+		$active_message_type_names = $this->list_of_active_message_types();
412
+		foreach ($active_message_type_names as $active_message_type_name) {
413
+			if (isset($installed_message_types[$active_message_type_name])) {
414
+				$active_message_types[$active_message_type_name] = $installed_message_types[$active_message_type_name];
415
+			}
416
+		}
417
+		return $active_message_types;
418
+	}
419
+
420
+
421
+	/**
422
+	 * @return \EE_message_type[]
423
+	 */
424
+	public function installed_message_types()
425
+	{
426
+		if (empty($this->_installed_message_types)) {
427
+			$this->message_type_collection()->rewind();
428
+			while ($this->message_type_collection()->valid()) {
429
+				$this->_installed_message_types[$this->message_type_collection()->current()->name] = $this->message_type_collection()->current();
430
+				$this->message_type_collection()->next();
431
+			}
432
+		}
433
+		return $this->_installed_message_types;
434
+	}
435
+
436
+
437
+	/**
438
+	 * @param string $message_type_name
439
+	 * @return \EE_message_type
440
+	 * @throws \EE_Error
441
+	 */
442
+	public function valid_message_type($message_type_name)
443
+	{
444
+		$message_type = $this->get_message_type($message_type_name);
445
+		if ($message_type instanceof EE_message_type) {
446
+			return $message_type;
447
+		}
448
+		throw new EE_Error(
449
+			sprintf(
450
+				__('The "%1$s" message type is either invalid or not installed', 'event_espresso'),
451
+				$message_type_name
452
+			)
453
+		);
454
+	}
455
+
456
+
457
+	/**
458
+	 * valid_message_type_for_messenger
459
+	 *
460
+	 * @param EE_messenger $messenger
461
+	 * @param string       $message_type_name
462
+	 * @return boolean
463
+	 * @throws \EE_Error
464
+	 */
465
+	public function valid_message_type_for_messenger(EE_messenger $messenger, $message_type_name)
466
+	{
467
+		$valid_message_types = $messenger->get_valid_message_types();
468
+		if (! in_array($message_type_name, $valid_message_types)) {
469
+			throw new EE_Error(
470
+				sprintf(
471
+					__(
472
+						'The message type (%1$s) sent to "%2$s" is not valid for the "%3$s" messenger.  Double-check the spelling and verify that message type has been registered as a valid type with the messenger.',
473
+						'event_espresso'
474
+					),
475
+					$message_type_name,
476
+					__METHOD__,
477
+					$messenger->name
478
+				)
479
+			);
480
+		}
481
+		return true;
482
+	}
483
+
484
+
485
+	/**
486
+	 * Used to return active messengers array stored in the wp options table.
487
+	 * If no value is present in the option then an empty array is returned.
488
+	 *
489
+	 * @param   bool $reset     If true then we ignore whether the option is cached on the _active_message_types
490
+	 *                          property and pull directly from the db.  Otherwise whatever is currently on the
491
+	 *                          $_active_message_types property is pulled.
492
+	 * @return array
493
+	 */
494
+	public function get_active_messengers_option($reset = false)
495
+	{
496
+		if ($reset) {
497
+			$this->_active_message_types = get_option('ee_active_messengers', array());
498
+		}
499
+		return $this->_active_message_types;
500
+	}
501
+
502
+
503
+	/**
504
+	 * Used to update the active messengers array stored in the wp options table.
505
+	 *
506
+	 * @param array $active_messenger_settings Incoming data to save.  If empty, then the internal cached property
507
+	 *                                         representing this data is used.
508
+	 * @return bool FALSE if not updated, TRUE if updated.
509
+	 */
510
+	public function update_active_messengers_option($active_messenger_settings = array())
511
+	{
512
+		$active_messenger_settings = empty($active_messenger_settings) ? $this->_active_message_types : $active_messenger_settings;
513
+		//make sure _active_message_types is updated (this is the internal cache for the settings).
514
+		$this->_active_message_types = $active_messenger_settings;
515
+		return update_option('ee_active_messengers', $active_messenger_settings);
516
+	}
517
+
518
+
519
+	/**
520
+	 * Used to return has activated message types for messengers array stored in the wp options table.
521
+	 * If no value is present in the option then an empty array is returned.
522
+	 * The value is cached on the $_has_activated_messengers_and_message_types property for future calls.
523
+	 * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
524
+	 *
525
+	 * @param   bool $reset Used to indicate that any cached value should be ignored.
526
+	 * @return array
527
+	 */
528
+	public function get_has_activated_messengers_option($reset = false)
529
+	{
530
+		if ($reset || empty($this->_has_activated_messengers_and_message_types)) {
531
+			$this->_has_activated_messengers_and_message_types = get_option(self::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME, array());
532
+		}
533
+		return $this->_has_activated_messengers_and_message_types;
534
+	}
535
+
536
+
537
+	/**
538
+	 * Used to update the has activated option in the db.
539
+	 *
540
+	 * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
541
+	 *
542
+	 * @param array $has_activated_messengers Incoming data to save.  If empty, then the internal cached property
543
+	 *                                        representing this data is used.
544
+	 * @return bool FALSE if not updated, TRUE if updated.
545
+	 */
546
+	public function update_has_activated_messengers_option($has_activated_messengers = array())
547
+	{
548
+		//make sure the option has been retrieved from first so we don't overwrite it accidentally.
549
+		if (empty($has_activated_messengers) && empty($this->_has_activated_messengers_and_message_types)) {
550
+			$this->get_has_activated_messengers_option();
551
+		}
552
+		$has_activated_messengers = empty($has_activated_messengers)
553
+			? $this->_has_activated_messengers_and_message_types
554
+			: $has_activated_messengers;
555
+		return update_option(self::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME, $has_activated_messengers);
556
+	}
557
+
558
+
559
+	/**
560
+	 * wrapper for _set_active_messengers_and_message_types()
561
+	 */
562
+	public function reset_active_messengers_and_message_types()
563
+	{
564
+		$this->_set_active_messengers_and_message_types();
565
+	}
566
+
567
+
568
+	/**
569
+	 * Generate list of active messengers and message types from collection.
570
+	 * This sets up the active messengers from what is present in the database.
571
+	 */
572
+	protected function _set_active_messengers_and_message_types()
573
+	{
574
+		//echo "\n\n " . __LINE__ . ") " . __METHOD__ . "() \n";
575
+		// list of activated messengers as set via the admin
576
+		// note calling `get_active_messengers_options` also initializes the _active_message_types property.
577
+		$this->get_active_messengers_option(true);
578
+		$this->ensure_messengers_are_active(array(), false, true);
579
+		$this->update_active_messengers_option();
580
+		$this->update_has_activated_messengers_option();
581
+	}
582
+
583
+
584
+	/**
585
+	 * Ensures that the specified messenger is currently active.
586
+	 * If not, activates it and its default message types.
587
+	 *
588
+	 * @param string $messenger_name
589
+	 * @param bool   $update_option Whether to update the option in the db or not.
590
+	 * @return boolean true if either already active or successfully activated.
591
+	 */
592
+	public function ensure_messenger_is_active($messenger_name, $update_option = true)
593
+	{
594
+		if (! isset($this->_active_messengers[$messenger_name])) {
595
+			try {
596
+				$this->activate_messenger($messenger_name, array(), $update_option);
597
+			} catch (EE_Error $e) {
598
+				EE_Error::add_error(
599
+					$e->getMessage(),
600
+					__FILE__,
601
+					__FUNCTION__,
602
+					__LINE__
603
+				);
604
+				return false;
605
+			}
606
+		}
607
+		return true;
608
+	}
609
+
610
+
611
+	/**
612
+	 * This ensures the given array of messenger names is active in the system.
613
+	 * Note, this method will not activate any NEW message types for the messenger when it is called. Instead,
614
+	 * it will automatically activate the default message types for the messenger if its not active.
615
+	 *
616
+	 * @param array $messenger_names  Array of messenger names for messengers to be activated.  If an empty array
617
+	 *                                (default) then will attempt to set the active messengers from the
618
+	 *                                activated_messengers option
619
+	 *                                (stored in $_active_message_types property).
620
+	 * @param bool  $update_option    Whether to update the related active messengers option.
621
+	 * @param bool  $verify           Whether to verify the messengers are installed before activating. Note if this is
622
+	 *                                set to true and a messenger is indicated as active, but is NOT installed, then it
623
+	 *                                will automatically be deactivated.
624
+	 */
625
+	public function ensure_messengers_are_active($messenger_names = array(), $update_option = true, $verify = false)
626
+	{
627
+		$messenger_names = empty($messenger_names) ? array_keys($this->_active_message_types) : $messenger_names;
628
+
629
+		$not_installed = array();
630
+		foreach ($messenger_names as $messenger_name) {
631
+			if ($verify && ! $this->messenger_collection()->has_by_name($messenger_name)) {
632
+				$not_installed[] = $messenger_name;
633
+				$this->deactivate_messenger($messenger_name);
634
+				continue;
635
+			}
636
+			$this->ensure_messenger_is_active($messenger_name, $update_option);
637
+		}
638
+
639
+		if (! empty($not_installed)) {
640
+			EE_Error::add_error(
641
+				sprintf(
642
+					__('The following messengers are either not installed or are invalid:%1$s %2$s', 'event_espresso'),
643
+					'<br />',
644
+					implode(', ', $not_installed)
645
+				),
646
+				__FILE__, __FUNCTION__, __LINE__
647
+			);
648
+		}
649
+	}
650
+
651
+
652
+	/**
653
+	 * Ensures that the specified message type for the given messenger is currently active, if not activates it.
654
+	 * This ALSO ensures that the given messenger is active as well!
655
+	 *
656
+	 * @param string $message_type_name message type name.
657
+	 * @param        $messenger_name
658
+	 * @param bool   $update_option     Whether to update the option in the db or not.
659
+	 * @return bool  Returns true if already is active or if was activated successfully.
660
+	 * @throws \EE_Error
661
+	 */
662
+	public function ensure_message_type_is_active($message_type_name, $messenger_name, $update_option = true)
663
+	{
664
+		// grab the messenger to work with.
665
+		$messenger = $this->valid_messenger($messenger_name);
666
+		if ($this->valid_message_type_for_messenger($messenger, $message_type_name)) {
667
+			//ensure messenger is active (that's an inherent coupling between active message types and the
668
+			//messenger they are being activated for.
669
+			try {
670
+				if (! $this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
671
+					//all is good so let's just get it active
672
+					$this->activate_messenger($messenger_name, array($message_type_name), $update_option);
673
+				}
674
+			} catch (EE_Error $e) {
675
+				EE_Error::add_error(
676
+					$e->getMessage(),
677
+					__FILE__,
678
+					__FUNCTION__,
679
+					__LINE__
680
+				);
681
+				return false;
682
+			}
683
+		}
684
+		return true;
685
+	}
686
+
687
+
688
+	/**
689
+	 * This is a wrapper for `ensure_message_type_is_active` that will handle ensuring multiple message types for a
690
+	 * messenger are active in one go.
691
+	 *
692
+	 * @param array  $message_type_names Array of message type names to ensure are active.
693
+	 * @param string $messenger_name     The name of the messenger that the message types are to be activated on.
694
+	 * @param bool   $update_option      Whether to persist the activation to the database or not (default true).
695
+	 */
696
+	public function ensure_message_types_are_active($message_type_names, $messenger_name, $update_option = true)
697
+	{
698
+		$message_type_names = (array)$message_type_names;
699
+		foreach ($message_type_names as $message_type_name) {
700
+			// note, intentionally not updating option here because we're in a loop.
701
+			// We'll follow the instructions of the incoming $update_option argument after the loop.
702
+			$this->ensure_message_type_is_active($message_type_name, $messenger_name, false);
703
+		}
704
+		if ($update_option) {
705
+			$this->update_active_messengers_option();
706
+			$this->update_has_activated_messengers_option();
707
+		}
708
+	}
709
+
710
+
711
+	/**
712
+	 * Activates the specified messenger.
713
+	 *
714
+	 * @param string $messenger_name
715
+	 * @param array  $message_type_names        An array of message type names to activate with this messenger.
716
+	 *                                          If included we do NOT setup the default message types
717
+	 *                                          (assuming they are already setup.)
718
+	 * @param bool   $update_active_messengers_option
719
+	 * @return array of generated templates
720
+	 * @throws \EE_Error
721
+	 */
722
+	public function activate_messenger(
723
+		$messenger_name,
724
+		$message_type_names = array(),
725
+		$update_active_messengers_option = true
726
+	) {
727
+		$templates = array();
728
+		// grab the messenger to work with.
729
+		$messenger = $this->messenger_collection()->get_by_info($messenger_name);
730
+		// it's inactive. Activate it.
731
+		if ($messenger instanceof EE_messenger) {
732
+			$this->_active_messengers[$messenger->name] = $messenger;
733
+			//activate incoming message types set to be activated with messenger.
734
+			$message_type_names = $this->_activate_message_types($messenger, $message_type_names);
735
+			// setup any initial settings for the messenger if necessary.
736
+			$this->add_settings_for_messenger($messenger->name);
737
+			if ($update_active_messengers_option) {
738
+				$this->update_active_messengers_option();
739
+				$this->update_has_activated_messengers_option();
740
+			}
741
+			//generate new templates if necessary and ensure all related templates that are already in the database are
742
+			//marked active.  Note, this will also deactivate a message type for a messenger if the template
743
+			//cannot be successfully created during its attempt (only happens for global template attempts).
744
+			if (! empty($message_type_names)) {
745
+				$templates = EEH_MSG_Template::generate_new_templates($messenger->name, $message_type_names, 0, true);
746
+				EEH_MSG_Template::update_to_active(array($messenger->name), $message_type_names);
747
+			}
748
+		}
749
+		return $templates;
750
+	}
751
+
752
+
753
+	/**
754
+	 * Activates given message types for the given EE_messenger object.
755
+	 * Note: (very important) This method does not persist the activation to the database.
756
+	 * See code implementing this method in this class for examples of how to persist.
757
+	 *
758
+	 * @param \EE_messenger $messenger
759
+	 * @param  array        $message_type_names
760
+	 * @return array
761
+	 */
762
+	protected function _activate_message_types(EE_messenger $messenger, $message_type_names = array())
763
+	{
764
+		//If $message_type_names is empty, AND $this->_active_message_types is empty, then that means
765
+		//things have never been initialized (which should happen on EEH_Activation::generate_message_templates).
766
+		//So ONLY then do we need to actually grab defaults and cycle through them.  Otherwise we
767
+		//only override _active_message_types when an explicit array of $message_type_names has been provided.
768
+		$message_type_names = empty($message_type_names) && ! isset($this->_active_message_types[$messenger->name])
769
+			? $messenger->get_default_message_types()
770
+			: (array)$message_type_names;
771
+
772
+		//now we ALWAYS need to make sure that the messenger is active for the message types we're activating!
773
+		if (! isset($this->_active_message_types[$messenger->name])) {
774
+			$this->_active_message_types[$messenger->name]['settings'] = array();
775
+		}
776
+
777
+		if ($message_type_names) {
778
+			// cycle thru message types
779
+			foreach ($message_type_names as $message_type_name) {
780
+				//only register the message type as active IF it isn't already active
781
+				//and if its actually installed.
782
+				if (
783
+				! $this->is_message_type_active_for_messenger($messenger->name, $message_type_name)
784
+				) {
785
+					$this->add_settings_for_message_type($messenger->name, $message_type_name);
786
+					$this->_set_messenger_has_activated_message_type(
787
+						$messenger,
788
+						$message_type_name
789
+					);
790
+				}
791
+			}
792
+		}
793
+		return $message_type_names;
794
+	}
795
+
796
+
797
+	/**
798
+	 * add_settings_for_message_type
799
+	 * NOTE This does NOT automatically persist any settings to the db.  Client code should call
800
+	 * $this->update_active_messengers_option to persist.
801
+	 *
802
+	 * @param  string $messenger_name    The name of the messenger adding the settings for
803
+	 * @param  string $message_type_name The name of the message type adding the settings for
804
+	 * @param  array  $new_settings      Any new settings being set for the message type and messenger
805
+	 */
806
+	public function add_settings_for_message_type($messenger_name, $message_type_name, $new_settings = array())
807
+	{
808
+		// get installed message type from collection
809
+		$message_type      = $this->message_type_collection()->get_by_info($message_type_name);
810
+		$existing_settings = $this->get_message_type_settings_for_messenger($messenger_name, $message_type_name);
811
+		//we need to setup any initial settings for message types
812
+		if ($message_type instanceof EE_message_type) {
813
+			$default_settings = $message_type->get_admin_settings_fields();
814
+			foreach ($default_settings as $field => $values) {
815
+				if (isset($new_settings[$field])) {
816
+					$existing_settings[$field] = $new_settings[$field];
817
+					continue;
818
+				}
819
+				if (! isset($existing_settings[$field])) {
820
+					$existing_settings[$field] = $values['default'];
821
+				}
822
+			}
823
+		}
824
+		$this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings'] = $existing_settings;
825
+	}
826
+
827
+
828
+	/**
829
+	 * Updates the internal cached _has_activated_messengers_and_message_types property with the given messenger
830
+	 * and message type.
831
+	 *
832
+	 * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
833
+	 *
834
+	 * @access protected
835
+	 * @param \EE_messenger $messenger
836
+	 * @param string        $message_type_name
837
+	 */
838
+	protected function _set_messenger_has_activated_message_type(EE_messenger $messenger, $message_type_name)
839
+	{
840
+
841
+		//if _has_activated_messengers_and_message_types is empty then lets ensure its initialized
842
+		if (empty($this->_has_activated_messengers_and_message_types)) {
843
+			$this->get_has_activated_messengers_option();
844
+		}
845
+
846
+		// make sure this messenger has a record in the has_activated array
847
+		if (! isset($this->_has_activated_messengers_and_message_types[$messenger->name])) {
848
+			$this->_has_activated_messengers_and_message_types[$messenger->name] = array();
849
+		}
850
+		// check if message type has already been added
851
+		if (! in_array($message_type_name, $this->_has_activated_messengers_and_message_types[$messenger->name])) {
852
+			$this->_has_activated_messengers_and_message_types[$messenger->name][] = $message_type_name;
853
+		}
854
+	}
855
+
856
+
857
+	/**
858
+	 * add_settings_for_messenger
859
+	 * NOTE This does NOT automatically persist any settings to the db.  Client code should call
860
+	 * $this->update_active_messengers_option to persist.
861
+	 *
862
+	 * @param string $messenger_name The name of the messenger the settings is being added for.
863
+	 * @param array  $new_settings   An array of settings to update the existing settings.
864
+	 */
865
+	public function add_settings_for_messenger($messenger_name, $new_settings = array())
866
+	{
867
+		$messenger = $this->get_messenger($messenger_name);
868
+		if ($messenger instanceof EE_messenger) {
869
+			$msgr_settings = $messenger->get_admin_settings_fields();
870
+			if (! empty($msgr_settings)) {
871
+				foreach ($msgr_settings as $field => $value) {
872
+					//is there a new setting for this?
873
+					if (isset($new_settings[$field])) {
874
+						$this->_active_message_types[$messenger->name]['settings'][$field] = $new_settings[$field];
875
+						continue;
876
+					}
877
+					//only set the default if it isn't already set.
878
+					if (! isset($this->_active_message_types[$messenger->name]['settings'][$field])) {
879
+						$this->_active_message_types[$messenger->name]['settings'][$field] = $value;
880
+					}
881
+				}
882
+			}
883
+		}
884
+	}
885
+
886
+
887
+	/**
888
+	 * deactivate_messenger
889
+	 *
890
+	 * @param  string|EE_messenger $messenger_name name of messenger
891
+	 * @return void
892
+	 */
893
+	public function deactivate_messenger($messenger_name)
894
+	{
895
+		$this->_initialize_collections();
896
+		if ($messenger_name instanceof EE_messenger) {
897
+			$messenger_name = $messenger_name->name;
898
+		}
899
+		unset($this->_active_messengers[$messenger_name]);
900
+		unset($this->_active_message_types[$messenger_name]);
901
+		$this->_message_template_group_model->deactivate_message_template_groups_for($messenger_name);
902
+		$this->update_active_messengers_option();
903
+	}
904
+
905
+
906
+	/**
907
+	 * Deactivates a message type (note this will deactivate across all messenger's it is active on.
908
+	 *
909
+	 * @param  string $message_type_name     name of message type being deactivated
910
+	 * @param bool    $set_has_active_record By default we always record the has_active record when deactivating a message
911
+	 *                                       type.  However, this can be overridden if we don't want this set (usually when
912
+	 *                                       this is called as a part of deregistration of a custom message type)
913
+	 */
914
+	public function deactivate_message_type($message_type_name, $set_has_active_record = true)
915
+	{
916
+		$this->_initialize_collections();
917
+		if ($message_type_name instanceof EE_message_type) {
918
+			$message_type_name = $message_type_name->name;
919
+		}
920
+		foreach ($this->_active_message_types as $messenger_name => $settings) {
921
+			unset(
922
+				$this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]
923
+			);
924
+
925
+			//we always record (even on deactivation) that a message type has been activated because there should at
926
+			//least be a record in the "has_activated" option that it WAS active at one point.
927
+			if ($set_has_active_record) {
928
+				$messenger = $this->get_messenger($messenger_name);
929
+				$this->_set_messenger_has_activated_message_type($messenger, $message_type_name);
930
+			}
931
+		}
932
+		$this->_message_template_group_model->deactivate_message_template_groups_for('', $message_type_name);
933
+		$this->update_active_messengers_option();
934
+		$this->update_has_activated_messengers_option();
935
+	}
936
+
937
+
938
+	/**
939
+	 * Deactivates a message type for a specific messenger as opposed to all messengers.
940
+	 *
941
+	 * @param string $message_type_name Name of message type being deactivated.
942
+	 * @param string $messenger_name    Name of messenger the message type is being deactivated for.
943
+	 */
944
+	public function deactivate_message_type_for_messenger($message_type_name, $messenger_name)
945
+	{
946
+		$this->_initialize_collections();
947
+		if ($this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
948
+			unset($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]);
949
+		}
950
+		$this->_message_template_group_model->deactivate_message_template_groups_for(array($messenger_name),
951
+			array($message_type_name));
952
+		$this->update_active_messengers_option();
953
+	}
954
+
955
+
956
+	/**
957
+	 * Used to verify if a message can be sent for the given messenger and message type
958
+	 * and that it is a generating messenger (used for generating message templates).
959
+	 *
960
+	 * @param EE_messenger    $messenger    messenger used in trigger
961
+	 * @param EE_message_type $message_type message type used in trigger
962
+	 * @return bool true is a generating messenger and can be sent OR FALSE meaning cannot send.
963
+	 */
964
+	public function is_generating_messenger_and_active(EE_messenger $messenger, EE_message_type $message_type)
965
+	{
966
+		//get the $messengers the message type says it can be used with.
967
+		foreach ($message_type->with_messengers() as $generating_messenger => $secondary_messengers) {
968
+			if (
969
+				$messenger->name === $generating_messenger
970
+				&& $this->is_message_type_active_for_messenger($messenger->name, $message_type->name)
971
+			) {
972
+				return true;
973
+			}
974
+		}
975
+		return false;
976
+	}
977
+
978
+
979
+	/**
980
+	 * This returns all the contexts that are registered by all message types.
981
+	 * If $slugs_only is true,
982
+	 * then just an array indexed by unique context slugs with the latest label representation for that slug.
983
+	 * array(
984
+	 *      'context_slug' => 'localized label for context obtained from latest message type in the loop'.
985
+	 * );
986
+	 * If $slugs_only is false, then the format is:
987
+	 * array(
988
+	 *      'message_type_name' => array(
989
+	 *          'context_slug' => array(
990
+	 *              'label' => 'localized label for context',
991
+	 *              'description' => 'localized description for context'
992
+	 *          )
993
+	 *      )
994
+	 * );
995
+	 * Keep in mind that although different message types may share the same context slugs,
996
+	 * it is possible that the context is described differently by the message type.
997
+	 *
998
+	 * @since 4.9.0
999
+	 * @param   bool $slugs_only Whether to return an array of just slugs and labels (true)
1000
+	 *                           or all contexts indexed by message type.
1001
+	 * @return array
1002
+	 */
1003
+	public function get_all_contexts($slugs_only = true)
1004
+	{
1005
+		$key = $slugs_only ? 'slugs' : 'all';
1006
+		// check if contexts has been setup yet.
1007
+		if (empty($this->_contexts[$key])) {
1008
+			// So let's get all active message type objects and loop through to get all unique contexts
1009
+			foreach ($this->get_active_message_type_objects() as $message_type) {
1010
+				if ($message_type instanceof EE_message_type) {
1011
+					$message_type_contexts = $message_type->get_contexts();
1012
+					if ($slugs_only) {
1013
+						foreach ($message_type_contexts as $context => $context_details) {
1014
+							$this->_contexts[$key][$context] = $context_details['label'];
1015
+						}
1016
+					} else {
1017
+						$this->_contexts[$key][$message_type->name] = $message_type_contexts;
1018
+					}
1019
+				}
1020
+			}
1021
+		}
1022
+		return ! empty($this->_contexts[$key]) ? $this->_contexts[$key] : array();
1023
+	}
1024
+
1025
+
1026
+	/**
1027
+	 * This checks the internal record of what message types are considered "active" and verifies that
1028
+	 * there is an installed class definition for that message type.  If the active message type does not have a
1029
+	 * corresponding accessible message type class then it will be deactivated from all messengers it is active on and
1030
+	 * any related message templates will be inactivated as well.
1031
+	 *
1032
+	 * @return bool   true means all active message types are valid, false means at least one message type was
1033
+	 *                deactivated.
1034
+	 */
1035
+	public function validate_active_message_types_are_installed()
1036
+	{
1037
+		$list_of_active_message_type_names = $this->list_of_active_message_types();
1038
+		$installed_message_types           = $this->installed_message_types();
1039
+		$all_message_types_valid           = true;
1040
+		//loop through list of active message types and verify they are installed.
1041
+		foreach ($list_of_active_message_type_names as $message_type_name) {
1042
+			if (! isset($installed_message_types[$message_type_name])) {
1043
+				$this->remove_message_type_has_been_activated_from_all_messengers(
1044
+					$message_type_name,
1045
+					true
1046
+				);
1047
+				$this->deactivate_message_type($message_type_name, false);
1048
+				$all_message_types_valid = false;
1049
+			}
1050
+		}
1051
+		return $all_message_types_valid;
1052
+	}
1053
+
1054
+
1055
+	/**
1056
+	 * This method checks the `ee_has_activated_messenger` option to see if the message type has ever been
1057
+	 * activated for the given messenger.  This can be called by client code on plugin updates etc to determine whether
1058
+	 * to attempt automatically reactivating message types that should be activated by default or not.
1059
+	 *
1060
+	 * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
1061
+	 *
1062
+	 * @param $message_type_name
1063
+	 * @param $messenger_name
1064
+	 * @return bool
1065
+	 */
1066
+	public function has_message_type_been_activated_for_messenger($message_type_name, $messenger_name)
1067
+	{
1068
+		$has_activated = $this->get_has_activated_messengers_option();
1069
+		return isset($has_activated[$messenger_name])
1070
+			   && in_array($message_type_name, $has_activated[$messenger_name]);
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * This method unsets a message type from the given messenger has activated option.
1076
+	 *
1077
+	 * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
1078
+	 *
1079
+	 * @param string $message_type_name
1080
+	 * @param string $messenger_name
1081
+	 * @param bool   $consider_current_state  Whether to consider whether the  message type is currently active or not.
1082
+	 *                                        If it is currently active, then remove.  Otherwise leave it alone.
1083
+	 */
1084
+	public function remove_message_type_has_been_activated_for_messenger(
1085
+		$message_type_name,
1086
+		$messenger_name,
1087
+		$consider_current_state = false
1088
+	) {
1089
+		if ($consider_current_state
1090
+			&& ! $this->is_message_type_active_for_messenger($messenger_name, $message_type_name)
1091
+		) {
1092
+			//when consider current state is true, this means we don't want to change anything on the "has_activated"
1093
+			//record if the message type is currently active for this messenger.  This is used when we want to retain
1094
+			//the record for user initiated inactivations of the message type.
1095
+			return;
1096
+		}
1097
+		$has_activated = $this->get_has_activated_messengers_option();
1098
+		$key_for_message_type = isset($has_activated[$messenger_name])
1099
+			? array_search($message_type_name, $has_activated[$messenger_name], true)
1100
+			: false;
1101
+		if ($key_for_message_type !== false) {
1102
+			unset($has_activated[$messenger_name][$key_for_message_type]);
1103
+			$this->update_has_activated_messengers_option($has_activated);
1104
+			//reset the internal cached property
1105
+			$this->get_has_activated_messengers_option(true);
1106
+		}
1107
+	}
1108
+
1109
+
1110
+	/**
1111
+	 * Removes a message type active record from all messengers it is attached to.
1112
+	 *
1113
+	 * @see phpdocs on EE_Message_Resource_Manager::HAS_ACTIVATED_MESSAGE_TYPE_FOR_MESSENGER_OPTION_NAME for more details.
1114
+	 *
1115
+	 * @param      $message_type_name
1116
+	 * @param bool $consider_current_state  Whether to consider whether the  message type is currently active or not.
1117
+	 *                                      If it is currently active, then remove.  Otherwise leave it alone.
1118
+	 */
1119
+	public function remove_message_type_has_been_activated_from_all_messengers(
1120
+		$message_type_name,
1121
+		$consider_current_state = false
1122
+	) {
1123
+		foreach(array_keys($this->get_has_activated_messengers_option()) as $messenger_name) {
1124
+			$this->remove_message_type_has_been_activated_for_messenger(
1125
+				$message_type_name,
1126
+				$messenger_name,
1127
+				$consider_current_state
1128
+			);
1129
+		}
1130
+	}
1131 1131
 }
1132 1132
 // End of file EE_Message_Resource_Manager.lib.php
1133 1133
 // Location: /EE_Message_Resource_Manager.lib.php
Please login to merge, or discard this patch.
Spacing   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -1,6 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-if (! defined('EVENT_ESPRESSO_VERSION')) {
3
+if ( ! defined('EVENT_ESPRESSO_VERSION')) {
4 4
     exit('No direct script access allowed');
5 5
 }
6 6
 
@@ -297,7 +297,7 @@  discard block
 block discarded – undo
297 297
     public function is_message_type_active_for_messenger($messenger_name, $message_type_name)
298 298
     {
299 299
         $this->_initialize_collections();
300
-        return ! empty($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]);
300
+        return ! empty($this->_active_message_types[$messenger_name]['settings'][$messenger_name.'-message_types'][$message_type_name]);
301 301
     }
302 302
 
303 303
 
@@ -325,8 +325,8 @@  discard block
 block discarded – undo
325 325
     {
326 326
         $settings = array();
327 327
         if ($this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
328
-            $settings = isset($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings'])
329
-                ? $this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings']
328
+            $settings = isset($this->_active_message_types[$messenger_name]['settings'][$messenger_name.'-message_types'][$message_type_name]['settings'])
329
+                ? $this->_active_message_types[$messenger_name]['settings'][$messenger_name.'-message_types'][$message_type_name]['settings']
330 330
                 : array();
331 331
         }
332 332
         return $settings;
@@ -345,7 +345,7 @@  discard block
 block discarded – undo
345 345
         $this->_initialize_collections();
346 346
         return
347 347
             ! empty($this->_active_message_types[$messenger_name])
348
-            && ! empty($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types']);
348
+            && ! empty($this->_active_message_types[$messenger_name]['settings'][$messenger_name.'-message_types']);
349 349
     }
350 350
 
351 351
 
@@ -360,7 +360,7 @@  discard block
 block discarded – undo
360 360
     public function get_active_message_types_for_messenger($messenger_name)
361 361
     {
362 362
         $message_types = array();
363
-        if (! $this->messenger_has_active_message_types($messenger_name)) {
363
+        if ( ! $this->messenger_has_active_message_types($messenger_name)) {
364 364
             return $message_types;
365 365
         }
366 366
         $installed_message_types = $this->installed_message_types();
@@ -385,11 +385,11 @@  discard block
 block discarded – undo
385 385
         $active_message_type_names = array();
386 386
         $this->_initialize_collections();
387 387
         foreach ($this->_active_message_types as $messenger => $messenger_settings) {
388
-            if (! isset($messenger_settings['settings'][$messenger . '-message_types'])) {
388
+            if ( ! isset($messenger_settings['settings'][$messenger.'-message_types'])) {
389 389
                 continue;
390 390
             }
391
-            foreach ($messenger_settings['settings'][$messenger . '-message_types'] as $message_type_name => $message_type_config) {
392
-                if (! in_array($message_type_name, $active_message_type_names)) {
391
+            foreach ($messenger_settings['settings'][$messenger.'-message_types'] as $message_type_name => $message_type_config) {
392
+                if ( ! in_array($message_type_name, $active_message_type_names)) {
393 393
                     $active_message_type_names[] = $message_type_name;
394 394
                 }
395 395
             }
@@ -465,7 +465,7 @@  discard block
 block discarded – undo
465 465
     public function valid_message_type_for_messenger(EE_messenger $messenger, $message_type_name)
466 466
     {
467 467
         $valid_message_types = $messenger->get_valid_message_types();
468
-        if (! in_array($message_type_name, $valid_message_types)) {
468
+        if ( ! in_array($message_type_name, $valid_message_types)) {
469 469
             throw new EE_Error(
470 470
                 sprintf(
471 471
                     __(
@@ -591,7 +591,7 @@  discard block
 block discarded – undo
591 591
      */
592 592
     public function ensure_messenger_is_active($messenger_name, $update_option = true)
593 593
     {
594
-        if (! isset($this->_active_messengers[$messenger_name])) {
594
+        if ( ! isset($this->_active_messengers[$messenger_name])) {
595 595
             try {
596 596
                 $this->activate_messenger($messenger_name, array(), $update_option);
597 597
             } catch (EE_Error $e) {
@@ -636,7 +636,7 @@  discard block
 block discarded – undo
636 636
             $this->ensure_messenger_is_active($messenger_name, $update_option);
637 637
         }
638 638
 
639
-        if (! empty($not_installed)) {
639
+        if ( ! empty($not_installed)) {
640 640
             EE_Error::add_error(
641 641
                 sprintf(
642 642
                     __('The following messengers are either not installed or are invalid:%1$s %2$s', 'event_espresso'),
@@ -667,7 +667,7 @@  discard block
 block discarded – undo
667 667
             //ensure messenger is active (that's an inherent coupling between active message types and the
668 668
             //messenger they are being activated for.
669 669
             try {
670
-                if (! $this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
670
+                if ( ! $this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
671 671
                     //all is good so let's just get it active
672 672
                     $this->activate_messenger($messenger_name, array($message_type_name), $update_option);
673 673
                 }
@@ -695,7 +695,7 @@  discard block
 block discarded – undo
695 695
      */
696 696
     public function ensure_message_types_are_active($message_type_names, $messenger_name, $update_option = true)
697 697
     {
698
-        $message_type_names = (array)$message_type_names;
698
+        $message_type_names = (array) $message_type_names;
699 699
         foreach ($message_type_names as $message_type_name) {
700 700
             // note, intentionally not updating option here because we're in a loop.
701 701
             // We'll follow the instructions of the incoming $update_option argument after the loop.
@@ -741,7 +741,7 @@  discard block
 block discarded – undo
741 741
             //generate new templates if necessary and ensure all related templates that are already in the database are
742 742
             //marked active.  Note, this will also deactivate a message type for a messenger if the template
743 743
             //cannot be successfully created during its attempt (only happens for global template attempts).
744
-            if (! empty($message_type_names)) {
744
+            if ( ! empty($message_type_names)) {
745 745
                 $templates = EEH_MSG_Template::generate_new_templates($messenger->name, $message_type_names, 0, true);
746 746
                 EEH_MSG_Template::update_to_active(array($messenger->name), $message_type_names);
747 747
             }
@@ -767,10 +767,10 @@  discard block
 block discarded – undo
767 767
         //only override _active_message_types when an explicit array of $message_type_names has been provided.
768 768
         $message_type_names = empty($message_type_names) && ! isset($this->_active_message_types[$messenger->name])
769 769
             ? $messenger->get_default_message_types()
770
-            : (array)$message_type_names;
770
+            : (array) $message_type_names;
771 771
 
772 772
         //now we ALWAYS need to make sure that the messenger is active for the message types we're activating!
773
-        if (! isset($this->_active_message_types[$messenger->name])) {
773
+        if ( ! isset($this->_active_message_types[$messenger->name])) {
774 774
             $this->_active_message_types[$messenger->name]['settings'] = array();
775 775
         }
776 776
 
@@ -816,12 +816,12 @@  discard block
 block discarded – undo
816 816
                     $existing_settings[$field] = $new_settings[$field];
817 817
                     continue;
818 818
                 }
819
-                if (! isset($existing_settings[$field])) {
819
+                if ( ! isset($existing_settings[$field])) {
820 820
                     $existing_settings[$field] = $values['default'];
821 821
                 }
822 822
             }
823 823
         }
824
-        $this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]['settings'] = $existing_settings;
824
+        $this->_active_message_types[$messenger_name]['settings'][$messenger_name.'-message_types'][$message_type_name]['settings'] = $existing_settings;
825 825
     }
826 826
 
827 827
 
@@ -844,11 +844,11 @@  discard block
 block discarded – undo
844 844
         }
845 845
 
846 846
         // make sure this messenger has a record in the has_activated array
847
-        if (! isset($this->_has_activated_messengers_and_message_types[$messenger->name])) {
847
+        if ( ! isset($this->_has_activated_messengers_and_message_types[$messenger->name])) {
848 848
             $this->_has_activated_messengers_and_message_types[$messenger->name] = array();
849 849
         }
850 850
         // check if message type has already been added
851
-        if (! in_array($message_type_name, $this->_has_activated_messengers_and_message_types[$messenger->name])) {
851
+        if ( ! in_array($message_type_name, $this->_has_activated_messengers_and_message_types[$messenger->name])) {
852 852
             $this->_has_activated_messengers_and_message_types[$messenger->name][] = $message_type_name;
853 853
         }
854 854
     }
@@ -867,7 +867,7 @@  discard block
 block discarded – undo
867 867
         $messenger = $this->get_messenger($messenger_name);
868 868
         if ($messenger instanceof EE_messenger) {
869 869
             $msgr_settings = $messenger->get_admin_settings_fields();
870
-            if (! empty($msgr_settings)) {
870
+            if ( ! empty($msgr_settings)) {
871 871
                 foreach ($msgr_settings as $field => $value) {
872 872
                     //is there a new setting for this?
873 873
                     if (isset($new_settings[$field])) {
@@ -875,7 +875,7 @@  discard block
 block discarded – undo
875 875
                         continue;
876 876
                     }
877 877
                     //only set the default if it isn't already set.
878
-                    if (! isset($this->_active_message_types[$messenger->name]['settings'][$field])) {
878
+                    if ( ! isset($this->_active_message_types[$messenger->name]['settings'][$field])) {
879 879
                         $this->_active_message_types[$messenger->name]['settings'][$field] = $value;
880 880
                     }
881 881
                 }
@@ -919,7 +919,7 @@  discard block
 block discarded – undo
919 919
         }
920 920
         foreach ($this->_active_message_types as $messenger_name => $settings) {
921 921
             unset(
922
-                $this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]
922
+                $this->_active_message_types[$messenger_name]['settings'][$messenger_name.'-message_types'][$message_type_name]
923 923
             );
924 924
 
925 925
             //we always record (even on deactivation) that a message type has been activated because there should at
@@ -945,7 +945,7 @@  discard block
 block discarded – undo
945 945
     {
946 946
         $this->_initialize_collections();
947 947
         if ($this->is_message_type_active_for_messenger($messenger_name, $message_type_name)) {
948
-            unset($this->_active_message_types[$messenger_name]['settings'][$messenger_name . '-message_types'][$message_type_name]);
948
+            unset($this->_active_message_types[$messenger_name]['settings'][$messenger_name.'-message_types'][$message_type_name]);
949 949
         }
950 950
         $this->_message_template_group_model->deactivate_message_template_groups_for(array($messenger_name),
951 951
             array($message_type_name));
@@ -1039,7 +1039,7 @@  discard block
 block discarded – undo
1039 1039
         $all_message_types_valid           = true;
1040 1040
         //loop through list of active message types and verify they are installed.
1041 1041
         foreach ($list_of_active_message_type_names as $message_type_name) {
1042
-            if (! isset($installed_message_types[$message_type_name])) {
1042
+            if ( ! isset($installed_message_types[$message_type_name])) {
1043 1043
                 $this->remove_message_type_has_been_activated_from_all_messengers(
1044 1044
                     $message_type_name,
1045 1045
                     true
@@ -1120,7 +1120,7 @@  discard block
 block discarded – undo
1120 1120
         $message_type_name,
1121 1121
         $consider_current_state = false
1122 1122
     ) {
1123
-        foreach(array_keys($this->get_has_activated_messengers_option()) as $messenger_name) {
1123
+        foreach (array_keys($this->get_has_activated_messengers_option()) as $messenger_name) {
1124 1124
             $this->remove_message_type_has_been_activated_for_messenger(
1125 1125
                 $message_type_name,
1126 1126
                 $messenger_name,
Please login to merge, or discard this patch.