Completed
Branch master (24c3eb)
by
unknown
34:49 queued 28:57
created
core/admin/EE_Admin_Page.core.php 2 patches
Indentation   +4231 added lines, -4231 removed lines patch added patch discarded remove patch
@@ -24,4324 +24,4324 @@
 block discarded – undo
24 24
  */
25 25
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
26 26
 {
27
-    protected ?EE_Admin_Config $admin_config       = null;
27
+	protected ?EE_Admin_Config $admin_config       = null;
28 28
 
29
-    protected ?EE_Admin_Hooks $_hook_obj          = null;
29
+	protected ?EE_Admin_Hooks $_hook_obj          = null;
30 30
 
31
-    protected ?EE_Admin_List_Table $_list_table_object = null;
31
+	protected ?EE_Admin_List_Table $_list_table_object = null;
32 32
 
33
-    protected ?EE_Capabilities $capabilities       = null;
33
+	protected ?EE_Capabilities $capabilities       = null;
34 34
 
35
-    protected ?EE_Registry $EE                 = null;
35
+	protected ?EE_Registry $EE                 = null;
36 36
 
37
-    protected ?FeatureFlags $feature            = null;
37
+	protected ?FeatureFlags $feature            = null;
38 38
 
39
-    protected ?LoaderInterface $loader             = null;
39
+	protected ?LoaderInterface $loader             = null;
40 40
 
41
-    protected ?RequestInterface $request            = null;
41
+	protected ?RequestInterface $request            = null;
42 42
 
43
-    protected ?WP_Screen $_current_screen    = null;
43
+	protected ?WP_Screen $_current_screen    = null;
44 44
 
45
-    /**
46
-     * @var array
47
-     * @since 5.0.0.p
48
-     */
49
-    private array $publish_post_meta_box_hidden_fields = [];
50
-
51
-    /**
52
-     * some default things shared by all child classes
53
-     *
54
-     * @var string[]
55
-     */
56
-    protected array $_default_espresso_metaboxes = [
57
-        '_espresso_news_post_box',
58
-        '_espresso_links_post_box',
59
-        '_espresso_ratings_request',
60
-        '_espresso_sponsors_post_box',
61
-    ];
62
-
63
-    /**
64
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
65
-     * actions.
66
-     *
67
-     * @since 4.6.x
68
-     */
69
-    protected array $_default_route_query_args = [];
70
-
71
-    protected array $_labels                   = [];
72
-
73
-    protected array $_nav_tabs                 = [];
74
-
75
-    protected array $_page_config              = [];
76
-
77
-    /**
78
-     * action => method pairs used for routing incoming requests
79
-     *
80
-     * @var array
81
-     */
82
-    protected array $_page_routes   = [];
83
-
84
-    protected array $_req_data      = [];
85
-
86
-    protected array $_route_config  = [];
87
-
88
-    protected array $_template_args = [];
89
-
90
-    protected array $_views         = [];
91
-
92
-    /**
93
-     * yes / no array for admin form fields
94
-     *
95
-     * @var array|array[]
96
-     */
97
-    protected array $_yes_no_values = [];
98
-
99
-    /**
100
-     * this starts at null so we can have no header routes progress through two states.
101
-     */
102
-    protected ?bool $_is_UI_request = null;
103
-
104
-    /**
105
-     * flags whether the given route is a caffeinated route or not.
106
-     */
107
-    protected bool $_is_caf        = false;
108
-
109
-    protected bool $_routing       = false;
110
-
111
-    /**
112
-     * whether initializePage() has run
113
-     *
114
-     * @var bool
115
-     */
116
-    protected bool $initialized = false;
117
-
118
-
119
-    protected string $_admin_base_path      = '';
120
-
121
-    protected string $_admin_base_url       = '';
122
-
123
-    protected string $_admin_page_title     = '';
124
-
125
-    protected string $_column_template_path = '';
126
-
127
-    protected bool $_cpt_route            = false;
128
-
129
-    /**
130
-     * set via request page and action args.
131
-     */
132
-    protected string $_current_page          = '';
133
-
134
-    protected string $_current_page_view_url = '';
135
-
136
-    protected string $_current_view          = '';
137
-
138
-    protected string $_default_nav_tab_name  = 'overview';
139
-
140
-    /**
141
-     * sanitized request action
142
-     */
143
-    protected string $_req_action = '';
144
-
145
-    /**
146
-     * sanitized request action nonce
147
-     */
148
-    protected string $_req_nonce        = '';
149
-
150
-    protected string $_search_btn_label = '';
151
-
152
-    protected string $_template_path    = '';
153
-
154
-    protected string $_view             = '';
155
-
156
-    /**
157
-     * set early within EE_Admin_Init
158
-     *
159
-     * @var string
160
-     */
161
-    protected string $_wp_page_slug = '';
162
-
163
-    /**
164
-     * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
165
-     * then this would be the parent classname: Events_Admin_Page
166
-     *
167
-     * @var string
168
-     */
169
-    public string $base_class_name = '';
170
-
171
-    public string $class_name      = '';
172
-
173
-    /**
174
-     * unprocessed value for the 'action' request param (default '')
175
-     *
176
-     * @var string
177
-     */
178
-    protected string $raw_req_action = '';
179
-
180
-    /**
181
-     * unprocessed value for the 'page' request param (default '')
182
-     *
183
-     * @var string
184
-     */
185
-    protected string $raw_req_page = '';
186
-
187
-    public string $page_folder  = '';
188
-
189
-    public string $page_label   = '';
190
-
191
-    public string $page_slug    = '';
192
-
193
-
194
-    /**
195
-     * the current page route and route config
196
-     *
197
-     * @var array|callable|string|null
198
-     */
199
-    protected $_route = null;
200
-
201
-
202
-    /**
203
-     * @Constructor
204
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
205
-     * @throws InvalidArgumentException
206
-     * @throws InvalidDataTypeException
207
-     * @throws InvalidInterfaceException
208
-     * @throws ReflectionException
209
-     */
210
-    public function __construct($routing = true)
211
-    {
212
-        $this->loader       = LoaderFactory::getLoader();
213
-        $this->admin_config = $this->loader->getShared(EE_Admin_Config::class);
214
-        $this->feature      = $this->loader->getShared(FeatureFlags::class);
215
-        $this->request      = $this->loader->getShared(RequestInterface::class);
216
-        $this->capabilities = $this->loader->getShared(EE_Capabilities::class);
217
-        // routing enabled?
218
-        $this->_routing = $routing;
219
-
220
-        $this->class_name      = get_class($this);
221
-        $this->base_class_name = strpos($this->class_name, 'Extend_') === 0
222
-            ? str_replace('Extend_', '', $this->class_name)
223
-            : '';
224
-
225
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
226
-            $this->_is_caf = true;
227
-        }
228
-        $this->_yes_no_values = [
229
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
230
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
231
-        ];
232
-        // set the _req_data property.
233
-        $this->_req_data = $this->request->requestParams();
234
-    }
235
-
236
-
237
-    /**
238
-     * @return EE_Admin_Config
239
-     */
240
-    public function adminConfig(): EE_Admin_Config
241
-    {
242
-        return $this->admin_config;
243
-    }
244
-
245
-
246
-    public function capabilities(): EE_Capabilities
247
-    {
248
-        if (! $this->capabilities instanceof EE_Capabilities) {
249
-            $this->capabilities = $this->loader->getShared(EE_Capabilities::class);
250
-        }
251
-        return $this->capabilities;
252
-    }
253
-
254
-
255
-    /**
256
-     * @return FeatureFlags
257
-     */
258
-    public function feature(): FeatureFlags
259
-    {
260
-        return $this->feature;
261
-    }
262
-
263
-
264
-    /**
265
-     * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
266
-     * for child classes that needed to set properties prior to these methods getting called,
267
-     * but also needed the parent class to have its construction completed as well.
268
-     * Bottom line is that constructors should ONLY be used for setting initial properties
269
-     * and any complex initialization logic should only run after instantiation is complete.
270
-     * This method gets called immediately after construction from within
271
-     *      EE_Admin_Page_Init::_initialize_admin_page()
272
-     *
273
-     * @throws EE_Error
274
-     * @throws InvalidArgumentException
275
-     * @throws InvalidDataTypeException
276
-     * @throws InvalidInterfaceException
277
-     * @throws ReflectionException
278
-     * @throws Throwable
279
-     * @since 5.0.0.p
280
-     */
281
-    public function initializePage()
282
-    {
283
-        if ($this->initialized) {
284
-            return;
285
-        }
286
-        // set initial page props (child method)
287
-        $this->_init_page_props();
288
-        // set global defaults
289
-        $this->_set_defaults();
290
-        // set early because incoming requests could be ajax related and we need to register those hooks.
291
-        if ($this->request->isAjax()) {
292
-            $this->_global_ajax_hooks();
293
-            $this->_ajax_hooks();
294
-        }
295
-        // other_page_hooks have to be early too.
296
-        $this->_do_other_page_hooks();
297
-        // set up page dependencies
298
-        $this->_before_page_setup();
299
-        $this->_page_setup();
300
-        $this->initialized = true;
301
-    }
302
-
303
-
304
-    /**
305
-     * _init_page_props
306
-     * Child classes use to set at least the following properties:
307
-     * $page_slug.
308
-     * $page_label.
309
-     *
310
-     * @abstract
311
-     * @return void
312
-     */
313
-    abstract protected function _init_page_props();
314
-
315
-
316
-    /**
317
-     * _ajax_hooks
318
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
319
-     * Note: within the ajax callback methods.
320
-     *
321
-     * @abstract
322
-     * @return void
323
-     */
324
-    abstract protected function _ajax_hooks();
325
-
326
-
327
-    /**
328
-     * _define_page_props
329
-     * child classes define page properties in here.  Must include at least:
330
-     * $_admin_base_url = base_url for all admin pages
331
-     * $_admin_page_title = default admin_page_title for admin pages
332
-     * $_labels = array of default labels for various automatically generated elements:
333
-     *    array(
334
-     *        'buttons' => array(
335
-     *            'add' => esc_html__('label for add new button'),
336
-     *            'edit' => esc_html__('label for edit button'),
337
-     *            'delete' => esc_html__('label for delete button')
338
-     *            )
339
-     *        )
340
-     *
341
-     * @abstract
342
-     * @return void
343
-     */
344
-    abstract protected function _define_page_props();
345
-
346
-
347
-    /**
348
-     * _set_page_routes
349
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
350
-     * assigned to an action => method pairs in an array and to the $_page_routes property.  Each page route must also
351
-     * have a 'default' route. Here's the format
352
-     * $this->_page_routes = array(
353
-     *        'default' => array(
354
-     *            'func' => '_default_method_handling_route',
355
-     *            'args' => array('array','of','args'),
356
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
357
-     *            ajax request, backend processing)
358
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
359
-     *            headers route after.  The string you enter here should match the defined route reference for a
360
-     *            headers sent route.
361
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
362
-     *            this route.
363
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
364
-     *            checks).
365
-     *        ),
366
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
367
-     *        handling method.
368
-     *        )
369
-     * )
370
-     *
371
-     * @abstract
372
-     * @return void
373
-     */
374
-    abstract protected function _set_page_routes();
375
-
376
-
377
-    /**
378
-     * _set_page_config
379
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
380
-     * array corresponds to the page_route for the loaded page. Format:
381
-     * $this->_page_config = array(
382
-     *        'default' => array(
383
-     *            'labels' => array(
384
-     *                'buttons' => array(
385
-     *                    'add' => esc_html__('label for adding item'),
386
-     *                    'edit' => esc_html__('label for editing item'),
387
-     *                    'delete' => esc_html__('label for deleting item')
388
-     *                ),
389
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
390
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
391
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
392
-     *            _define_page_props() method
393
-     *            'nav' => array(
394
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
395
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
396
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
397
-     *                'order' => 10, //required to indicate tab position.
398
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
399
-     *                displayed then add this parameter.
400
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
401
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
402
-     *            metaboxes set for eventespresso admin pages.
403
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
404
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
405
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
406
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
407
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
408
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
409
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
410
-     *            There is an option in the "screen_options" dropdown that is set up so users can pick what columns they
411
-     *            want to display.
412
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
413
-     *                'tab_id' => array(
414
-     *                    'title' => 'tab_title',
415
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
416
-     *                    help tab content.  The fallback if it isn't present is to try the callback.  Filename
417
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
418
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
419
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
420
-     *                    attempt to use the callback which should match the name of a method in the class
421
-     *                    ),
422
-     *                'tab2_id' => array(
423
-     *                    'title' => 'tab2 title',
424
-     *                    'filename' => 'file_name_2'
425
-     *                    'callback' => 'callback_method_for_content',
426
-     *                 ),
427
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
428
-     *            help tab area on an admin page. @return void
429
-     *
430
-     * @abstract
431
-     */
432
-    abstract protected function _set_page_config();
433
-
434
-
435
-    /**
436
-     * _add_screen_options
437
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
438
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
439
-     * to a particular view.
440
-     *
441
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
442
-     *         see also WP_Screen object documents...
443
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
444
-     * @abstract
445
-     * @return void
446
-     */
447
-    abstract protected function _add_screen_options();
448
-
449
-
450
-    /**
451
-     * _add_feature_pointers
452
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
453
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
454
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
455
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (it's a final class so can't be
456
-     * extended) also see:
457
-     *
458
-     * @link   http://eamann.com/tech/wordpress-portland/
459
-     * @abstract
460
-     * @return void
461
-     */
462
-    abstract protected function _add_feature_pointers();
463
-
464
-
465
-    /**
466
-     * load_scripts_styles
467
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
468
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
469
-     * scripts/styles per view by putting them in a dynamic function in this format
470
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
471
-     *
472
-     * @abstract
473
-     * @return void
474
-     */
475
-    abstract public function load_scripts_styles();
476
-
477
-
478
-    /**
479
-     * admin_init
480
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
481
-     * all pages/views loaded by child class.
482
-     *
483
-     * @abstract
484
-     * @return void
485
-     */
486
-    abstract public function admin_init();
487
-
488
-
489
-    /**
490
-     * admin_notices
491
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
492
-     * all pages/views loaded by child class.
493
-     *
494
-     * @abstract
495
-     * @return void
496
-     */
497
-    abstract public function admin_notices();
498
-
499
-
500
-    /**
501
-     * admin_footer_scripts
502
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
503
-     * will apply to all pages/views loaded by child class.
504
-     *
505
-     * @return void
506
-     */
507
-    abstract public function admin_footer_scripts();
508
-
509
-
510
-    /**
511
-     * admin_footer
512
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
513
-     * apply to all pages/views loaded by child class.
514
-     *
515
-     * @return void
516
-     */
517
-    public function admin_footer()
518
-    {
519
-    }
520
-
521
-
522
-    /**
523
-     * _global_ajax_hooks
524
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
525
-     * Note: within the ajax callback methods.
526
-     *
527
-     * @abstract
528
-     * @return void
529
-     */
530
-    protected function _global_ajax_hooks()
531
-    {
532
-        // for lazy loading of metabox content
533
-        add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content']);
534
-
535
-        add_action(
536
-            'wp_ajax_espresso_hide_status_change_notice',
537
-            [$this, 'hideStatusChangeNotice']
538
-        );
539
-        add_action(
540
-            'wp_ajax_nopriv_espresso_hide_status_change_notice',
541
-            [$this, 'hideStatusChangeNotice']
542
-        );
543
-    }
544
-
545
-
546
-    public function ajax_metabox_content()
547
-    {
548
-        $content_id  = $this->request->getRequestParam('contentid', '');
549
-        $content_url = $this->request->getRequestParam('contenturl', '', DataType::URL);
550
-        EE_Admin_Page::cached_rss_display($content_id, $content_url);
551
-        wp_die();
552
-    }
553
-
554
-
555
-    public function hideStatusChangeNotice()
556
-    {
557
-        $response = [];
558
-        try {
559
-            /** @var StatusChangeNotice $status_change_notice */
560
-            $status_change_notice = $this->loader->getShared(
561
-                'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
562
-            );
563
-            $response['success']  = $status_change_notice->dismiss() > -1;
564
-        } catch (Exception $exception) {
565
-            $response['errors'] = $exception->getMessage();
566
-        }
567
-        wp_send_json($response);
568
-    }
45
+	/**
46
+	 * @var array
47
+	 * @since 5.0.0.p
48
+	 */
49
+	private array $publish_post_meta_box_hidden_fields = [];
569 50
 
51
+	/**
52
+	 * some default things shared by all child classes
53
+	 *
54
+	 * @var string[]
55
+	 */
56
+	protected array $_default_espresso_metaboxes = [
57
+		'_espresso_news_post_box',
58
+		'_espresso_links_post_box',
59
+		'_espresso_ratings_request',
60
+		'_espresso_sponsors_post_box',
61
+	];
570 62
 
571
-    /**
572
-     * allows extending classes do something specific before the parent constructor runs _page_setup().
573
-     *
574
-     * @return void
575
-     */
576
-    protected function _before_page_setup()
577
-    {
578
-        // default is to do nothing
579
-    }
63
+	/**
64
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
65
+	 * actions.
66
+	 *
67
+	 * @since 4.6.x
68
+	 */
69
+	protected array $_default_route_query_args = [];
580 70
 
71
+	protected array $_labels                   = [];
581 72
 
582
-    /**
583
-     * Makes sure any things that need to be loaded early get handled.
584
-     * We also escape early here if the page requested doesn't match the object.
585
-     *
586
-     * @final
587
-     * @return void
588
-     * @throws EE_Error
589
-     * @throws InvalidArgumentException
590
-     * @throws ReflectionException
591
-     * @throws InvalidDataTypeException
592
-     * @throws InvalidInterfaceException
593
-     * @throws Throwable
594
-     */
595
-    final protected function _page_setup()
596
-    {
597
-        // requires?
598
-        // admin_init stuff - global - we're setting this REALLY early
599
-        // so if EE_Admin pages have to hook into other WP pages they can.
600
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
601
-        add_action('admin_init', [$this, 'admin_init_global'], 5);
602
-        // next verify if we need to load anything...
603
-        $this->_current_page = $this->request->getRequestParam('page', '', DataType::KEY);
604
-        $this->_current_page = $this->request->getRequestParam('current_page', $this->_current_page, DataType::KEY);
605
-        $this->page_folder   = strtolower(
606
-            str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
607
-        );
608
-        global $ee_menu_slugs;
609
-        $ee_menu_slugs = (array) $ee_menu_slugs;
610
-        if (
611
-            ! $this->request->isAjax()
612
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
613
-        ) {
614
-            return;
615
-        }
616
-        // because WP List tables have two duplicate select inputs for choosing bulk actions,
617
-        // we need to copy the action from the second to the first
618
-        $action     = $this->request->getRequestParam('action', '-1', DataType::KEY);
619
-        $action2    = $this->request->getRequestParam('action2', '-1', DataType::KEY);
620
-        $action     = $action !== '-1' ? $action : $action2;
621
-        $req_action = $action !== '-1' ? $action : 'default';
622
-
623
-        // if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
624
-        // then let's use the route as the action.
625
-        // This covers cases where we're coming in from a list table that isn't on the default route.
626
-        $route = $this->request->getRequestParam('route');
627
-        $route = $route !== '-1' ? $route : 'default';
628
-        $this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
629
-            ? $route
630
-            : $req_action;
631
-        $this->_current_view = $this->_req_action;
632
-        $this->_req_nonce    = $this->_req_action . '_nonce';
633
-        $this->_define_page_props();
634
-        $this->_current_page_view_url = add_query_arg(
635
-            ['page' => $this->_current_page, 'action' => $this->_current_view],
636
-            $this->_admin_base_url
637
-        );
638
-        // set page configs
639
-        $this->_set_page_routes();
640
-        $this->_set_page_config();
641
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
642
-        if ($this->request->requestParamIsSet('wp_referer')) {
643
-            $wp_referer = $this->request->getRequestParam('wp_referer');
644
-            if ($wp_referer) {
645
-                $this->_default_route_query_args['wp_referer'] = $wp_referer;
646
-            }
647
-        }
648
-        // for CPT and other extended functionality.
649
-        // If there is an _extend_page_config_for_cpt
650
-        // then let's run that to modify all the various page configuration arrays.
651
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
652
-            $this->_extend_page_config_for_cpt();
653
-        }
654
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
655
-        $this->_page_routes = apply_filters(
656
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
657
-            $this->_page_routes,
658
-            $this
659
-        );
660
-        $this->_page_config = apply_filters(
661
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
662
-            $this->_page_config,
663
-            $this
664
-        );
665
-        if ($this->base_class_name !== '') {
666
-            $this->_page_routes = apply_filters(
667
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
668
-                $this->_page_routes,
669
-                $this
670
-            );
671
-            $this->_page_config = apply_filters(
672
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
673
-                $this->_page_config,
674
-                $this
675
-            );
676
-        }
677
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
678
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
679
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
680
-            add_action(
681
-                'AHEE__EE_Admin_Page__route_admin_request',
682
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
683
-                10,
684
-                2
685
-            );
686
-        }
687
-        // next route only if routing enabled
688
-        if ($this->_routing && ! $this->request->isAjax()) {
689
-            $this->_verify_routes();
690
-            // next let's just check user_access and kill if no access
691
-            $this->check_user_access();
692
-            if ($this->_is_UI_request) {
693
-                // admin_init stuff - global, all views for this page class, specific view
694
-                add_action('admin_init', [$this, 'admin_init']);
695
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
696
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
697
-                }
698
-            } else {
699
-                // hijack regular WP loading and route admin request immediately
700
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
701
-                $this->route_admin_request();
702
-            }
703
-        }
704
-    }
73
+	protected array $_nav_tabs                 = [];
705 74
 
75
+	protected array $_page_config              = [];
706 76
 
707
-    /**
708
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
709
-     *
710
-     * @return void
711
-     * @throws EE_Error
712
-     */
713
-    private function _do_other_page_hooks()
714
-    {
715
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
716
-        foreach ($registered_pages as $page) {
717
-            // now let's set up the file name and class that should be present
718
-            $classname = str_replace('.class.php', '', $page);
719
-            // autoloaders should take care of loading file
720
-            if (! class_exists($classname)) {
721
-                $error_msg[] = sprintf(
722
-                    esc_html__(
723
-                        'Something went wrong with loading the %s admin hooks page.',
724
-                        'event_espresso'
725
-                    ),
726
-                    $page
727
-                );
728
-                $error_msg[] = $error_msg[0]
729
-                               . "\r\n"
730
-                               . sprintf(
731
-                                   esc_html__(
732
-                                       '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',
733
-                                       'event_espresso'
734
-                                   ),
735
-                                   $page,
736
-                                   '<br />',
737
-                                   '<strong>' . $classname . '</strong>'
738
-                               );
739
-                throw new EE_Error(implode('||', $error_msg));
740
-            }
741
-            // don't load the same class twice
742
-            static $loaded = [];
743
-            if (in_array($classname, $loaded, true)) {
744
-                continue;
745
-            }
746
-            $loaded[] = $classname;
747
-            // notice we are passing the instance of this class to the hook object.
748
-            $this->loader->getShared($classname, [$this]);
749
-        }
750
-    }
77
+	/**
78
+	 * action => method pairs used for routing incoming requests
79
+	 *
80
+	 * @var array
81
+	 */
82
+	protected array $_page_routes   = [];
751 83
 
84
+	protected array $_req_data      = [];
752 85
 
753
-    /**
754
-     * @throws ReflectionException
755
-     * @throws EE_Error
756
-     */
757
-    public function load_page_dependencies()
758
-    {
759
-        try {
760
-            $this->_load_page_dependencies();
761
-        } catch (EE_Error $e) {
762
-            $e->get_error();
763
-        }
764
-    }
86
+	protected array $_route_config  = [];
765 87
 
88
+	protected array $_template_args = [];
766 89
 
767
-    /**
768
-     * load_page_dependencies
769
-     * loads things specific to this page class when it's loaded.  Really helps with efficiency.
770
-     *
771
-     * @return void
772
-     * @throws DomainException
773
-     * @throws EE_Error
774
-     * @throws InvalidArgumentException
775
-     * @throws InvalidDataTypeException
776
-     * @throws InvalidInterfaceException
777
-     * @throws ReflectionException
778
-     */
779
-    protected function _load_page_dependencies()
780
-    {
781
-        // let's set the current_screen and screen options to override what WP set
782
-        $this->_current_screen = get_current_screen();
783
-        // load admin_notices - global, page class, and view specific
784
-        add_action('admin_notices', [$this, 'admin_notices_global'], 5);
785
-        add_action('admin_notices', [$this, 'admin_notices']);
786
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
787
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
788
-        }
789
-        // load network admin_notices - global, page class, and view specific
790
-        add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
791
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
792
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
793
-        }
794
-        // this will save any per_page screen options if they are present
795
-        $this->_set_per_page_screen_options();
796
-        // setup list table properties
797
-        $this->_set_list_table();
798
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
799
-        // However in some cases the metaboxes will need to be added within a route handling callback.
800
-        add_action('add_meta_boxes', [$this, 'addRegisteredMetaBoxes'], 99);
801
-        // hack because promos admin was loading the edited promotion object in the metaboxes callback
802
-        // which should NOT be generated on non-UI requests like POST updates/inserts
803
-        if (
804
-            $this->class_name === 'Promotions_Admin_Page'
805
-            && ($this->_req_action === 'edit' || $this->_req_action === 'create_new')
806
-        ) {
807
-            $this->addRegisteredMetaBoxes();
808
-        }
809
-        $this->_add_screen_columns();
810
-        // add screen options - global, page child class, and view specific
811
-        $this->_add_global_screen_options();
812
-        $this->_add_screen_options();
813
-        $add_screen_options = "_add_screen_options_$this->_current_view";
814
-        if (method_exists($this, $add_screen_options)) {
815
-            $this->{$add_screen_options}();
816
-        }
817
-        // add help tab(s) - set via page_config and qtips.
818
-        $this->_add_help_tabs();
819
-        $this->_add_qtips();
820
-        // add feature_pointers - global, page child class, and view specific
821
-        $this->_add_feature_pointers();
822
-        $this->_add_global_feature_pointers();
823
-        $add_feature_pointer = "_add_feature_pointer_$this->_current_view";
824
-        if (method_exists($this, $add_feature_pointer)) {
825
-            $this->{$add_feature_pointer}();
826
-        }
827
-        // enqueue scripts/styles - global, page class, and view specific
828
-        add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 1);
829
-        add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
830
-        add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles']);
831
-        if (method_exists($this, "load_scripts_styles_$this->_current_view")) {
832
-            add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_$this->_current_view"], 15);
833
-        }
834
-        // admin_print_footer_scripts - global, page child class, and view specific.
835
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
836
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
837
-        // is a good use case. Notice the late priority we're giving these
838
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
839
-        add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
840
-        if (method_exists($this, "admin_footer_scripts_$this->_current_view")) {
841
-            add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_$this->_current_view"], 101);
842
-        }
843
-        // admin footer scripts
844
-        add_action('admin_footer', [$this, 'admin_footer_global'], 99);
845
-        add_action('admin_footer', [$this, 'admin_footer'], 100);
846
-        if (method_exists($this, "admin_footer_$this->_current_view")) {
847
-            add_action('admin_footer', [$this, "admin_footer_$this->_current_view"], 101);
848
-        }
849
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
850
-        // targeted hook
851
-        do_action(
852
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__$this->_req_action"
853
-        );
854
-    }
90
+	protected array $_views         = [];
855 91
 
92
+	/**
93
+	 * yes / no array for admin form fields
94
+	 *
95
+	 * @var array|array[]
96
+	 */
97
+	protected array $_yes_no_values = [];
856 98
 
857
-    /**
858
-     * _set_defaults
859
-     * This sets some global defaults for class properties.
860
-     */
861
-    private function _set_defaults()
862
-    {
863
-        // init template args
864
-        $this->set_template_args(
865
-            [
866
-                'admin_page_header'  => '',
867
-                'admin_page_content' => '',
868
-                'post_body_content'  => '',
869
-                'before_list_table'  => '',
870
-                'after_list_table'   => '',
871
-            ]
872
-        );
873
-    }
99
+	/**
100
+	 * this starts at null so we can have no header routes progress through two states.
101
+	 */
102
+	protected ?bool $_is_UI_request = null;
874 103
 
104
+	/**
105
+	 * flags whether the given route is a caffeinated route or not.
106
+	 */
107
+	protected bool $_is_caf        = false;
875 108
 
876
-    /**
877
-     * route_admin_request
878
-     *
879
-     * @return void
880
-     * @throws InvalidArgumentException
881
-     * @throws InvalidInterfaceException
882
-     * @throws InvalidDataTypeException
883
-     * @throws EE_Error
884
-     * @throws ReflectionException
885
-     * @throws Throwable
886
-     * @see    _route_admin_request()
887
-     */
888
-    public function route_admin_request()
889
-    {
890
-        try {
891
-            $this->_route_admin_request();
892
-        } catch (EE_Error $e) {
893
-            $e->get_error();
894
-        }
895
-    }
896
-
897
-
898
-    public function set_wp_page_slug($wp_page_slug)
899
-    {
900
-        $this->_wp_page_slug = $wp_page_slug;
901
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
902
-        if (is_network_admin()) {
903
-            $this->_wp_page_slug .= '-network';
904
-        }
905
-    }
109
+	protected bool $_routing       = false;
906 110
 
111
+	/**
112
+	 * whether initializePage() has run
113
+	 *
114
+	 * @var bool
115
+	 */
116
+	protected bool $initialized = false;
907 117
 
908
-    /**
909
-     * _verify_routes
910
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
911
-     * we know if we need to drop out.
912
-     *
913
-     * @return bool
914
-     * @throws EE_Error
915
-     */
916
-    protected function _verify_routes(): bool
917
-    {
918
-        if (! $this->_current_page && ! $this->request->isAjax()) {
919
-            return false;
920
-        }
921
-        // check that the page_routes array is not empty
922
-        if (empty($this->_page_routes)) {
923
-            // user error msg
924
-            $error_msg = sprintf(
925
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
926
-                $this->_admin_page_title
927
-            );
928
-            // developer error msg
929
-            $error_msg .= '||' . $error_msg
930
-                          . esc_html__(
931
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
932
-                              'event_espresso'
933
-                          );
934
-            throw new EE_Error($error_msg);
935
-        }
936
-        // route 'editpost' routes to CPT 'edit' routes
937
-        $alt_edit_route = $this instanceof EE_Admin_Page_CPT ? $this->cpt_editpost_route : 'edit';
938
-        if (
939
-            $this->_req_action === 'editpost'
940
-            && ! isset($this->_page_routes['editpost'])
941
-            && isset($this->_page_routes[ $alt_edit_route ])
942
-        ) {
943
-            $this->_req_action = $alt_edit_route;
944
-        }
945
-        // and that the requested page route exists
946
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
947
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
948
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
949
-        } else {
950
-            // user error msg
951
-            $error_msg = sprintf(
952
-                esc_html__(
953
-                    'The requested page route does not exist for the %s admin page.',
954
-                    'event_espresso'
955
-                ),
956
-                $this->_admin_page_title
957
-            );
958
-            // developer error msg
959
-            $error_msg .= '||' . $error_msg
960
-                          . sprintf(
961
-                              esc_html__(
962
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
963
-                                  'event_espresso'
964
-                              ),
965
-                              $this->_req_action
966
-                          );
967
-            throw new EE_Error($error_msg);
968
-        }
969
-        // and that a default route exists
970
-        if (! array_key_exists('default', $this->_page_routes)) {
971
-            // user error msg
972
-            $error_msg = sprintf(
973
-                esc_html__(
974
-                    'A default page route has not been set for the % admin page.',
975
-                    'event_espresso'
976
-                ),
977
-                $this->_admin_page_title
978
-            );
979
-            // developer error msg
980
-            $error_msg .= '||' . $error_msg
981
-                          . esc_html__(
982
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
983
-                              'event_espresso'
984
-                          );
985
-            throw new EE_Error($error_msg);
986
-        }
987
-
988
-        // first lets' catch if the UI request has EVER been set.
989
-        if ($this->_is_UI_request === null) {
990
-            // let's set if this is a UI request or not.
991
-            $this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, DataType::BOOL);
992
-            // wait a minute... we might have a noheader in the route array
993
-            $this->_is_UI_request = ! (isset($this->_route['noheader']) && $this->_route['noheader'])
994
-                ? $this->_is_UI_request
995
-                : false;
996
-        }
997
-        $this->_set_current_labels();
998
-        return true;
999
-    }
1000 118
 
119
+	protected string $_admin_base_path      = '';
1001 120
 
1002
-    /**
1003
-     * this method simply verifies a given route and makes sure it's an actual route available for the loaded page
1004
-     *
1005
-     * @param string $route the route name we're verifying
1006
-     * @return bool we'll throw an exception if this isn't a valid route.
1007
-     * @throws EE_Error
1008
-     */
1009
-    protected function _verify_route(string $route): bool
1010
-    {
1011
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
1012
-            return true;
1013
-        }
1014
-        // user error msg
1015
-        $error_msg = sprintf(
1016
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1017
-            $this->_admin_page_title
1018
-        );
1019
-        // developer error msg
1020
-        $error_msg .= '||' . $error_msg
1021
-                      . sprintf(
1022
-                          esc_html__(
1023
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1024
-                              'event_espresso'
1025
-                          ),
1026
-                          $route
1027
-                      );
1028
-        throw new EE_Error($error_msg);
1029
-    }
121
+	protected string $_admin_base_url       = '';
1030 122
 
123
+	protected string $_admin_page_title     = '';
1031 124
 
1032
-    /**
1033
-     * perform nonce verification
1034
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1035
-     * using this method (and save retyping!)
1036
-     *
1037
-     * @param string $nonce     The nonce sent
1038
-     * @param string $nonce_ref The nonce reference string (name0)
1039
-     * @return void
1040
-     * @throws EE_Error
1041
-     * @throws InvalidArgumentException
1042
-     * @throws InvalidDataTypeException
1043
-     * @throws InvalidInterfaceException
1044
-     */
1045
-    protected function _verify_nonce(string $nonce, string $nonce_ref)
1046
-    {
1047
-        // verify nonce against expected value
1048
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1049
-            // these are not the droids you are looking for !!!
1050
-            $msg = sprintf(
1051
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
1052
-                '<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1053
-                '</a>'
1054
-            );
1055
-            if (WP_DEBUG) {
1056
-                $msg .= "\n  ";
1057
-                $msg .= sprintf(
1058
-                    esc_html__(
1059
-                        'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1060
-                        'event_espresso'
1061
-                    ),
1062
-                    __CLASS__
1063
-                );
1064
-            }
1065
-            if (! $this->request->isAjax()) {
1066
-                wp_die($msg);
1067
-            }
1068
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1069
-            $this->_return_json();
1070
-        }
1071
-    }
125
+	protected string $_column_template_path = '';
1072 126
 
127
+	protected bool $_cpt_route            = false;
1073 128
 
1074
-    /**
1075
-     * _route_admin_request()
1076
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1077
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1078
-     * in the page routes and then will try to load the corresponding method.
1079
-     *
1080
-     * @return void
1081
-     * @throws EE_Error
1082
-     * @throws InvalidArgumentException
1083
-     * @throws InvalidDataTypeException
1084
-     * @throws InvalidInterfaceException
1085
-     * @throws ReflectionException
1086
-     * @throws Throwable
1087
-     */
1088
-    protected function _route_admin_request()
1089
-    {
1090
-        if (! $this->_is_UI_request) {
1091
-            $this->_verify_routes();
1092
-        }
1093
-        $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1094
-        if ($this->_req_action !== 'default' && $nonce_check) {
1095
-            // set nonce from post data
1096
-            $nonce = $this->request->getRequestParam($this->_req_nonce, '');
1097
-            $this->_verify_nonce($nonce, $this->_req_nonce);
1098
-        }
1099
-        // set the nav_tabs array but ONLY if this is  UI_request
1100
-        if ($this->_is_UI_request) {
1101
-            $this->_set_nav_tabs();
1102
-        }
1103
-        // grab callback function
1104
-        $func = $this->_route['func'] ?? $this->_route;
1105
-        // check if callback has args
1106
-        $args = $this->_route['args'] ?? [];
1107
-
1108
-        // action right before calling route
1109
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1110
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1111
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1112
-        }
1113
-        // strip _wp_http_referer from the server REQUEST_URI
1114
-        // else it grows in length on every submission due to recursion,
1115
-        // ultimately causing a "Request-URI Too Large" error
1116
-        $this->request->unSetRequestParam('_wp_http_referer');
1117
-        $this->request->unSetServerParam('_wp_http_referer');
1118
-        $cleaner_request_uri = remove_query_arg(
1119
-            '_wp_http_referer',
1120
-            wp_unslash($this->request->getServerParam('REQUEST_URI'))
1121
-        );
1122
-        $this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1123
-        $this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1124
-        $route_callback = [];
1125
-        if (! empty($func)) {
1126
-            if (is_array($func) && is_callable($func)) {
1127
-                $route_callback = $func;
1128
-            } elseif (is_string($func)) {
1129
-                if (strpos($func, '::') !== false) {
1130
-                    $route_callback = explode('::', $func);
1131
-                } elseif (method_exists($this, $func)) {
1132
-                    $route_callback = [$this, $func];
1133
-                } else {
1134
-                    $route_callback = $func;
1135
-                }
1136
-            }
1137
-            [$class, $method] = $route_callback;
1138
-            // is it neither a class method NOR a standalone function?
1139
-            if (! is_callable($route_callback)) {
1140
-                // user error msg
1141
-                $error_msg = esc_html__(
1142
-                    'An error occurred. The  requested page route could not be found.',
1143
-                    'event_espresso'
1144
-                );
1145
-                // developer error msg
1146
-                $error_msg .= '||';
1147
-                $error_msg .= sprintf(
1148
-                    esc_html__(
1149
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1150
-                        'event_espresso'
1151
-                    ),
1152
-                    $method
1153
-                );
1154
-                throw new DomainException($error_msg);
1155
-            }
1156
-            if ($class !== $this && ! in_array($this, $args)) {
1157
-                // send along this admin page object for access by addons.
1158
-                $args['admin_page'] = $this;
1159
-            }
1160
-
1161
-            call_user_func_array($route_callback, $args);
1162
-        }
1163
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1164
-        // then we need to reset the routing properties to the new route.
1165
-        // 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.
1166
-        if (
1167
-            $this->_is_UI_request === false
1168
-            && is_array($this->_route)
1169
-            && ! empty($this->_route['headers_sent_route'])
1170
-        ) {
1171
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1172
-        }
1173
-    }
129
+	/**
130
+	 * set via request page and action args.
131
+	 */
132
+	protected string $_current_page          = '';
1174 133
 
134
+	protected string $_current_page_view_url = '';
1175 135
 
1176
-    /**
1177
-     * This method just allows the resetting of page properties in the case where a no headers
1178
-     * route redirects to a headers route in its route config.
1179
-     *
1180
-     * @param string $new_route New (non header) route to redirect to.
1181
-     * @return void
1182
-     * @throws ReflectionException
1183
-     * @throws InvalidArgumentException
1184
-     * @throws InvalidInterfaceException
1185
-     * @throws InvalidDataTypeException
1186
-     * @throws EE_Error
1187
-     * @throws Throwable
1188
-     * @since   4.3.0
1189
-     */
1190
-    protected function _reset_routing_properties(string $new_route)
1191
-    {
1192
-        $this->_is_UI_request = true;
1193
-        // now we set the current route to whatever the headers_sent_route is set at
1194
-        $this->request->setRequestParam('action', $new_route);
1195
-        // rerun page setup
1196
-        $this->_page_setup();
1197
-    }
136
+	protected string $_current_view          = '';
1198 137
 
138
+	protected string $_default_nav_tab_name  = 'overview';
139
+
140
+	/**
141
+	 * sanitized request action
142
+	 */
143
+	protected string $_req_action = '';
144
+
145
+	/**
146
+	 * sanitized request action nonce
147
+	 */
148
+	protected string $_req_nonce        = '';
149
+
150
+	protected string $_search_btn_label = '';
151
+
152
+	protected string $_template_path    = '';
153
+
154
+	protected string $_view             = '';
155
+
156
+	/**
157
+	 * set early within EE_Admin_Init
158
+	 *
159
+	 * @var string
160
+	 */
161
+	protected string $_wp_page_slug = '';
1199 162
 
1200
-    /**
1201
-     * _add_query_arg
1202
-     * adds nonce to array of arguments then calls WP add_query_arg function
1203
-     *(internally just uses EEH_URL's function with the same name)
1204
-     *
1205
-     * @param array  $args
1206
-     * @param string $url
1207
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1208
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1209
-     *                                        Example usage: If the current page is:
1210
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1211
-     *                                        &action=default&event_id=20&month_range=March%202015
1212
-     *                                        &_wpnonce=5467821
1213
-     *                                        and you call:
1214
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1215
-     *                                        array(
1216
-     *                                        'action' => 'resend_something',
1217
-     *                                        'page=>espresso_registrations'
1218
-     *                                        ),
1219
-     *                                        $some_url,
1220
-     *                                        true
1221
-     *                                        );
1222
-     *                                        It will produce a URL in this structure:
1223
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1224
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1225
-     *                                        month_range]=March%202015
1226
-     * @param bool   $exclude_nonce           If true, the nonce will be excluded from the generated nonce.
1227
-     * @param int    $context
1228
-     * @return string
1229
-     */
1230
-    public static function add_query_args_and_nonce(
1231
-        array $args = [],
1232
-        string $url = '',
1233
-        bool $sticky = false,
1234
-        bool $exclude_nonce = false,
1235
-        int $context = EEH_URL::CONTEXT_NONE
1236
-    ): string {
1237
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1238
-        if ($sticky) {
1239
-            /** @var RequestInterface $request */
1240
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1241
-            $request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1242
-            $request->unSetServerParam('_wp_http_referer', true);
1243
-            foreach ($request->requestParams() as $key => $value) {
1244
-                // do not add nonces
1245
-                if (strpos($key, 'nonce') !== false) {
1246
-                    continue;
1247
-                }
1248
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1249
-            }
1250
-        }
1251
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce, $context);
1252
-    }
163
+	/**
164
+	 * if the current class is an admin page extension, like: Extend_Events_Admin_Page,
165
+	 * then this would be the parent classname: Events_Admin_Page
166
+	 *
167
+	 * @var string
168
+	 */
169
+	public string $base_class_name = '';
1253 170
 
1254
-
1255
-    /**
1256
-     * This returns a generated link that will load the related help tab.
1257
-     *
1258
-     * @param string $help_tab_id the id for the connected help tab
1259
-     * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1260
-     * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1261
-     * @return string              generated link
1262
-     * @uses EEH_Template::get_help_tab_link()
1263
-     */
1264
-    protected function _get_help_tab_link(string $help_tab_id, string $icon_style = '', string $help_text = ''): string
1265
-    {
1266
-        return EEH_Template::get_help_tab_link(
1267
-            $help_tab_id,
1268
-            $this->page_slug,
1269
-            $this->_req_action,
1270
-            $icon_style,
1271
-            $help_text
1272
-        );
1273
-    }
1274
-
1275
-
1276
-    /**
1277
-     * _add_help_tabs
1278
-     * Note child classes define their help tabs within the page_config array.
1279
-     *
1280
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1281
-     * @return void
1282
-     * @throws DomainException
1283
-     * @throws EE_Error
1284
-     * @throws ReflectionException
1285
-     */
1286
-    protected function _add_help_tabs()
1287
-    {
1288
-        if (isset($this->_page_config[ $this->_req_action ])) {
1289
-            $config = $this->_page_config[ $this->_req_action ];
1290
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1291
-            if (is_array($config) && isset($config['help_sidebar'])) {
1292
-                // check that the callback given is valid
1293
-                if (! method_exists($this, $config['help_sidebar'])) {
1294
-                    throw new EE_Error(
1295
-                        sprintf(
1296
-                            esc_html__(
1297
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Double check the spelling and make sure this method exists for the class %s',
1298
-                                'event_espresso'
1299
-                            ),
1300
-                            $config['help_sidebar'],
1301
-                            $this->class_name
1302
-                        )
1303
-                    );
1304
-                }
1305
-                $content = apply_filters(
1306
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1307
-                    $this->{$config['help_sidebar']}()
1308
-                );
1309
-                $this->_current_screen->set_help_sidebar($content);
1310
-            }
1311
-            if (! isset($config['help_tabs'])) {
1312
-                return;
1313
-            } //no help tabs for this route
1314
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1315
-                // we're here so there ARE help tabs!
1316
-                // make sure we've got what we need
1317
-                if (! isset($cfg['title'])) {
1318
-                    throw new EE_Error(
1319
-                        esc_html__(
1320
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1321
-                            'event_espresso'
1322
-                        )
1323
-                    );
1324
-                }
1325
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1326
-                    throw new EE_Error(
1327
-                        esc_html__(
1328
-                            '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',
1329
-                            'event_espresso'
1330
-                        )
1331
-                    );
1332
-                }
1333
-                // first priority goes to content.
1334
-                if (! empty($cfg['content'])) {
1335
-                    $content = $cfg['content'];
1336
-                    // second priority goes to filename
1337
-                } elseif (! empty($cfg['filename'])) {
1338
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1339
-                    // 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)
1340
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1341
-                                                             . basename($this->_get_dir())
1342
-                                                             . '/help_tabs/'
1343
-                                                             . $cfg['filename']
1344
-                                                             . '.help_tab.php' : $file_path;
1345
-                    // if file is STILL not readable then let's do an EE_Error so its more graceful than a fatal error.
1346
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1347
-                        EE_Error::add_error(
1348
-                            sprintf(
1349
-                                esc_html__(
1350
-                                    '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',
1351
-                                    'event_espresso'
1352
-                                ),
1353
-                                $tab_id,
1354
-                                key($config),
1355
-                                $file_path
1356
-                            ),
1357
-                            __FILE__,
1358
-                            __FUNCTION__,
1359
-                            __LINE__
1360
-                        );
1361
-                        return;
1362
-                    }
1363
-                    $template_args['admin_page_obj'] = $this;
1364
-                    $content                         = EEH_Template::display_template(
1365
-                        $file_path,
1366
-                        $template_args,
1367
-                        true
1368
-                    );
1369
-                } else {
1370
-                    $content = '';
1371
-                }
1372
-                // check if callback is valid
1373
-                if (
1374
-                    empty($content)
1375
-                    && (
1376
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1377
-                    )
1378
-                ) {
1379
-                    EE_Error::add_error(
1380
-                        sprintf(
1381
-                            esc_html__(
1382
-                                '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.',
1383
-                                'event_espresso'
1384
-                            ),
1385
-                            $cfg['title']
1386
-                        ),
1387
-                        __FILE__,
1388
-                        __FUNCTION__,
1389
-                        __LINE__
1390
-                    );
1391
-                    return;
1392
-                }
1393
-                // setup config array for help tab method
1394
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1395
-                $_ht = [
1396
-                    'id'       => $id,
1397
-                    'title'    => $cfg['title'],
1398
-                    'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1399
-                    'content'  => $content,
1400
-                ];
1401
-                $this->_current_screen->add_help_tab($_ht);
1402
-            }
1403
-        }
1404
-    }
1405
-
1406
-
1407
-    /**
1408
-     * This simply sets up any qtips that have been defined in the page config
1409
-     *
1410
-     * @return void
1411
-     * @throws ReflectionException
1412
-     * @throws EE_Error
1413
-     */
1414
-    protected function _add_qtips()
1415
-    {
1416
-        if (isset($this->_route_config['qtips'])) {
1417
-            $qtips = (array) $this->_route_config['qtips'];
1418
-            // load qtip loader
1419
-            $path = [
1420
-                $this->_get_dir() . '/qtips/',
1421
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1422
-            ];
1423
-            EEH_Qtip_Loader::instance()->register($qtips, $path);
1424
-        }
1425
-    }
1426
-
1427
-
1428
-    /**
1429
-     * _set_nav_tabs
1430
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1431
-     * wish to add additional tabs or modify accordingly.
1432
-     *
1433
-     * @return void
1434
-     * @throws InvalidArgumentException
1435
-     * @throws InvalidInterfaceException
1436
-     * @throws InvalidDataTypeException
1437
-     */
1438
-    protected function _set_nav_tabs()
1439
-    {
1440
-        $i        = 0;
1441
-        $only_tab = count($this->_page_config) < 2;
1442
-        foreach ($this->_page_config as $slug => $config) {
1443
-            if (! is_array($config) || empty($config['nav'])) {
1444
-                continue;
1445
-            }
1446
-            // no nav tab for this config
1447
-            // check for persistent flag
1448
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1449
-                // nav tab is only to appear when route requested.
1450
-                continue;
1451
-            }
1452
-            if (! $this->check_user_access($slug, true)) {
1453
-                // no nav tab because current user does not have access.
1454
-                continue;
1455
-            }
1456
-            $css_class = $config['css_class'] ?? '';
1457
-            $css_class .= $only_tab ? ' ee-only-tab' : '';
1458
-            $css_class .= " ee-nav-tab__$slug";
1459
-
1460
-            $this->_nav_tabs[ $slug ] = [
1461
-                'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1462
-                    ['action' => $slug],
1463
-                    $this->_admin_base_url
1464
-                ),
1465
-                'link_text' => $this->navTabLabel($config['nav'], $slug),
1466
-                'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1467
-                'order'     => $config['nav']['order'] ?? $i,
1468
-            ];
1469
-            $i++;
1470
-        }
1471
-        // if $this->_nav_tabs is empty then lets set the default
1472
-        if (empty($this->_nav_tabs)) {
1473
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1474
-                'url'       => $this->_admin_base_url,
1475
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1476
-                'css_class' => 'nav-tab-active',
1477
-                'order'     => 10,
1478
-            ];
1479
-        }
1480
-        // now let's sort the tabs according to order
1481
-        usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1482
-    }
1483
-
1484
-
1485
-    private function navTabLabel(array $nav_tab, string $slug): string
1486
-    {
1487
-        $label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1488
-        $icon  = $nav_tab['icon'] ?? null;
1489
-        $icon  = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1490
-        return '
171
+	public string $class_name      = '';
172
+
173
+	/**
174
+	 * unprocessed value for the 'action' request param (default '')
175
+	 *
176
+	 * @var string
177
+	 */
178
+	protected string $raw_req_action = '';
179
+
180
+	/**
181
+	 * unprocessed value for the 'page' request param (default '')
182
+	 *
183
+	 * @var string
184
+	 */
185
+	protected string $raw_req_page = '';
186
+
187
+	public string $page_folder  = '';
188
+
189
+	public string $page_label   = '';
190
+
191
+	public string $page_slug    = '';
192
+
193
+
194
+	/**
195
+	 * the current page route and route config
196
+	 *
197
+	 * @var array|callable|string|null
198
+	 */
199
+	protected $_route = null;
200
+
201
+
202
+	/**
203
+	 * @Constructor
204
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
205
+	 * @throws InvalidArgumentException
206
+	 * @throws InvalidDataTypeException
207
+	 * @throws InvalidInterfaceException
208
+	 * @throws ReflectionException
209
+	 */
210
+	public function __construct($routing = true)
211
+	{
212
+		$this->loader       = LoaderFactory::getLoader();
213
+		$this->admin_config = $this->loader->getShared(EE_Admin_Config::class);
214
+		$this->feature      = $this->loader->getShared(FeatureFlags::class);
215
+		$this->request      = $this->loader->getShared(RequestInterface::class);
216
+		$this->capabilities = $this->loader->getShared(EE_Capabilities::class);
217
+		// routing enabled?
218
+		$this->_routing = $routing;
219
+
220
+		$this->class_name      = get_class($this);
221
+		$this->base_class_name = strpos($this->class_name, 'Extend_') === 0
222
+			? str_replace('Extend_', '', $this->class_name)
223
+			: '';
224
+
225
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
226
+			$this->_is_caf = true;
227
+		}
228
+		$this->_yes_no_values = [
229
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
230
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
231
+		];
232
+		// set the _req_data property.
233
+		$this->_req_data = $this->request->requestParams();
234
+	}
235
+
236
+
237
+	/**
238
+	 * @return EE_Admin_Config
239
+	 */
240
+	public function adminConfig(): EE_Admin_Config
241
+	{
242
+		return $this->admin_config;
243
+	}
244
+
245
+
246
+	public function capabilities(): EE_Capabilities
247
+	{
248
+		if (! $this->capabilities instanceof EE_Capabilities) {
249
+			$this->capabilities = $this->loader->getShared(EE_Capabilities::class);
250
+		}
251
+		return $this->capabilities;
252
+	}
253
+
254
+
255
+	/**
256
+	 * @return FeatureFlags
257
+	 */
258
+	public function feature(): FeatureFlags
259
+	{
260
+		return $this->feature;
261
+	}
262
+
263
+
264
+	/**
265
+	 * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
266
+	 * for child classes that needed to set properties prior to these methods getting called,
267
+	 * but also needed the parent class to have its construction completed as well.
268
+	 * Bottom line is that constructors should ONLY be used for setting initial properties
269
+	 * and any complex initialization logic should only run after instantiation is complete.
270
+	 * This method gets called immediately after construction from within
271
+	 *      EE_Admin_Page_Init::_initialize_admin_page()
272
+	 *
273
+	 * @throws EE_Error
274
+	 * @throws InvalidArgumentException
275
+	 * @throws InvalidDataTypeException
276
+	 * @throws InvalidInterfaceException
277
+	 * @throws ReflectionException
278
+	 * @throws Throwable
279
+	 * @since 5.0.0.p
280
+	 */
281
+	public function initializePage()
282
+	{
283
+		if ($this->initialized) {
284
+			return;
285
+		}
286
+		// set initial page props (child method)
287
+		$this->_init_page_props();
288
+		// set global defaults
289
+		$this->_set_defaults();
290
+		// set early because incoming requests could be ajax related and we need to register those hooks.
291
+		if ($this->request->isAjax()) {
292
+			$this->_global_ajax_hooks();
293
+			$this->_ajax_hooks();
294
+		}
295
+		// other_page_hooks have to be early too.
296
+		$this->_do_other_page_hooks();
297
+		// set up page dependencies
298
+		$this->_before_page_setup();
299
+		$this->_page_setup();
300
+		$this->initialized = true;
301
+	}
302
+
303
+
304
+	/**
305
+	 * _init_page_props
306
+	 * Child classes use to set at least the following properties:
307
+	 * $page_slug.
308
+	 * $page_label.
309
+	 *
310
+	 * @abstract
311
+	 * @return void
312
+	 */
313
+	abstract protected function _init_page_props();
314
+
315
+
316
+	/**
317
+	 * _ajax_hooks
318
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
319
+	 * Note: within the ajax callback methods.
320
+	 *
321
+	 * @abstract
322
+	 * @return void
323
+	 */
324
+	abstract protected function _ajax_hooks();
325
+
326
+
327
+	/**
328
+	 * _define_page_props
329
+	 * child classes define page properties in here.  Must include at least:
330
+	 * $_admin_base_url = base_url for all admin pages
331
+	 * $_admin_page_title = default admin_page_title for admin pages
332
+	 * $_labels = array of default labels for various automatically generated elements:
333
+	 *    array(
334
+	 *        'buttons' => array(
335
+	 *            'add' => esc_html__('label for add new button'),
336
+	 *            'edit' => esc_html__('label for edit button'),
337
+	 *            'delete' => esc_html__('label for delete button')
338
+	 *            )
339
+	 *        )
340
+	 *
341
+	 * @abstract
342
+	 * @return void
343
+	 */
344
+	abstract protected function _define_page_props();
345
+
346
+
347
+	/**
348
+	 * _set_page_routes
349
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
350
+	 * assigned to an action => method pairs in an array and to the $_page_routes property.  Each page route must also
351
+	 * have a 'default' route. Here's the format
352
+	 * $this->_page_routes = array(
353
+	 *        'default' => array(
354
+	 *            'func' => '_default_method_handling_route',
355
+	 *            'args' => array('array','of','args'),
356
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
357
+	 *            ajax request, backend processing)
358
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
359
+	 *            headers route after.  The string you enter here should match the defined route reference for a
360
+	 *            headers sent route.
361
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
362
+	 *            this route.
363
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
364
+	 *            checks).
365
+	 *        ),
366
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
367
+	 *        handling method.
368
+	 *        )
369
+	 * )
370
+	 *
371
+	 * @abstract
372
+	 * @return void
373
+	 */
374
+	abstract protected function _set_page_routes();
375
+
376
+
377
+	/**
378
+	 * _set_page_config
379
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
380
+	 * array corresponds to the page_route for the loaded page. Format:
381
+	 * $this->_page_config = array(
382
+	 *        'default' => array(
383
+	 *            'labels' => array(
384
+	 *                'buttons' => array(
385
+	 *                    'add' => esc_html__('label for adding item'),
386
+	 *                    'edit' => esc_html__('label for editing item'),
387
+	 *                    'delete' => esc_html__('label for deleting item')
388
+	 *                ),
389
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
390
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
391
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
392
+	 *            _define_page_props() method
393
+	 *            'nav' => array(
394
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
395
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
396
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
397
+	 *                'order' => 10, //required to indicate tab position.
398
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
399
+	 *                displayed then add this parameter.
400
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
401
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
402
+	 *            metaboxes set for eventespresso admin pages.
403
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
404
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
405
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
406
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
407
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
408
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
409
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
410
+	 *            There is an option in the "screen_options" dropdown that is set up so users can pick what columns they
411
+	 *            want to display.
412
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
413
+	 *                'tab_id' => array(
414
+	 *                    'title' => 'tab_title',
415
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
416
+	 *                    help tab content.  The fallback if it isn't present is to try the callback.  Filename
417
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
418
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
419
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
420
+	 *                    attempt to use the callback which should match the name of a method in the class
421
+	 *                    ),
422
+	 *                'tab2_id' => array(
423
+	 *                    'title' => 'tab2 title',
424
+	 *                    'filename' => 'file_name_2'
425
+	 *                    'callback' => 'callback_method_for_content',
426
+	 *                 ),
427
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
428
+	 *            help tab area on an admin page. @return void
429
+	 *
430
+	 * @abstract
431
+	 */
432
+	abstract protected function _set_page_config();
433
+
434
+
435
+	/**
436
+	 * _add_screen_options
437
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
438
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
439
+	 * to a particular view.
440
+	 *
441
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
442
+	 *         see also WP_Screen object documents...
443
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
444
+	 * @abstract
445
+	 * @return void
446
+	 */
447
+	abstract protected function _add_screen_options();
448
+
449
+
450
+	/**
451
+	 * _add_feature_pointers
452
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
453
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
454
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
455
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (it's a final class so can't be
456
+	 * extended) also see:
457
+	 *
458
+	 * @link   http://eamann.com/tech/wordpress-portland/
459
+	 * @abstract
460
+	 * @return void
461
+	 */
462
+	abstract protected function _add_feature_pointers();
463
+
464
+
465
+	/**
466
+	 * load_scripts_styles
467
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
468
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
469
+	 * scripts/styles per view by putting them in a dynamic function in this format
470
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
471
+	 *
472
+	 * @abstract
473
+	 * @return void
474
+	 */
475
+	abstract public function load_scripts_styles();
476
+
477
+
478
+	/**
479
+	 * admin_init
480
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
481
+	 * all pages/views loaded by child class.
482
+	 *
483
+	 * @abstract
484
+	 * @return void
485
+	 */
486
+	abstract public function admin_init();
487
+
488
+
489
+	/**
490
+	 * admin_notices
491
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
492
+	 * all pages/views loaded by child class.
493
+	 *
494
+	 * @abstract
495
+	 * @return void
496
+	 */
497
+	abstract public function admin_notices();
498
+
499
+
500
+	/**
501
+	 * admin_footer_scripts
502
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
503
+	 * will apply to all pages/views loaded by child class.
504
+	 *
505
+	 * @return void
506
+	 */
507
+	abstract public function admin_footer_scripts();
508
+
509
+
510
+	/**
511
+	 * admin_footer
512
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
513
+	 * apply to all pages/views loaded by child class.
514
+	 *
515
+	 * @return void
516
+	 */
517
+	public function admin_footer()
518
+	{
519
+	}
520
+
521
+
522
+	/**
523
+	 * _global_ajax_hooks
524
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
525
+	 * Note: within the ajax callback methods.
526
+	 *
527
+	 * @abstract
528
+	 * @return void
529
+	 */
530
+	protected function _global_ajax_hooks()
531
+	{
532
+		// for lazy loading of metabox content
533
+		add_action('wp_ajax_espresso-ajax-content', [$this, 'ajax_metabox_content']);
534
+
535
+		add_action(
536
+			'wp_ajax_espresso_hide_status_change_notice',
537
+			[$this, 'hideStatusChangeNotice']
538
+		);
539
+		add_action(
540
+			'wp_ajax_nopriv_espresso_hide_status_change_notice',
541
+			[$this, 'hideStatusChangeNotice']
542
+		);
543
+	}
544
+
545
+
546
+	public function ajax_metabox_content()
547
+	{
548
+		$content_id  = $this->request->getRequestParam('contentid', '');
549
+		$content_url = $this->request->getRequestParam('contenturl', '', DataType::URL);
550
+		EE_Admin_Page::cached_rss_display($content_id, $content_url);
551
+		wp_die();
552
+	}
553
+
554
+
555
+	public function hideStatusChangeNotice()
556
+	{
557
+		$response = [];
558
+		try {
559
+			/** @var StatusChangeNotice $status_change_notice */
560
+			$status_change_notice = $this->loader->getShared(
561
+				'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
562
+			);
563
+			$response['success']  = $status_change_notice->dismiss() > -1;
564
+		} catch (Exception $exception) {
565
+			$response['errors'] = $exception->getMessage();
566
+		}
567
+		wp_send_json($response);
568
+	}
569
+
570
+
571
+	/**
572
+	 * allows extending classes do something specific before the parent constructor runs _page_setup().
573
+	 *
574
+	 * @return void
575
+	 */
576
+	protected function _before_page_setup()
577
+	{
578
+		// default is to do nothing
579
+	}
580
+
581
+
582
+	/**
583
+	 * Makes sure any things that need to be loaded early get handled.
584
+	 * We also escape early here if the page requested doesn't match the object.
585
+	 *
586
+	 * @final
587
+	 * @return void
588
+	 * @throws EE_Error
589
+	 * @throws InvalidArgumentException
590
+	 * @throws ReflectionException
591
+	 * @throws InvalidDataTypeException
592
+	 * @throws InvalidInterfaceException
593
+	 * @throws Throwable
594
+	 */
595
+	final protected function _page_setup()
596
+	{
597
+		// requires?
598
+		// admin_init stuff - global - we're setting this REALLY early
599
+		// so if EE_Admin pages have to hook into other WP pages they can.
600
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
601
+		add_action('admin_init', [$this, 'admin_init_global'], 5);
602
+		// next verify if we need to load anything...
603
+		$this->_current_page = $this->request->getRequestParam('page', '', DataType::KEY);
604
+		$this->_current_page = $this->request->getRequestParam('current_page', $this->_current_page, DataType::KEY);
605
+		$this->page_folder   = strtolower(
606
+			str_replace(['_Admin_Page', 'Extend_'], '', $this->class_name)
607
+		);
608
+		global $ee_menu_slugs;
609
+		$ee_menu_slugs = (array) $ee_menu_slugs;
610
+		if (
611
+			! $this->request->isAjax()
612
+			&& (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
613
+		) {
614
+			return;
615
+		}
616
+		// because WP List tables have two duplicate select inputs for choosing bulk actions,
617
+		// we need to copy the action from the second to the first
618
+		$action     = $this->request->getRequestParam('action', '-1', DataType::KEY);
619
+		$action2    = $this->request->getRequestParam('action2', '-1', DataType::KEY);
620
+		$action     = $action !== '-1' ? $action : $action2;
621
+		$req_action = $action !== '-1' ? $action : 'default';
622
+
623
+		// if a specific 'route' has been set, and the action is 'default' OR we are doing_ajax
624
+		// then let's use the route as the action.
625
+		// This covers cases where we're coming in from a list table that isn't on the default route.
626
+		$route = $this->request->getRequestParam('route');
627
+		$route = $route !== '-1' ? $route : 'default';
628
+		$this->_req_action = $route && ($req_action === 'default' || $this->request->isAjax())
629
+			? $route
630
+			: $req_action;
631
+		$this->_current_view = $this->_req_action;
632
+		$this->_req_nonce    = $this->_req_action . '_nonce';
633
+		$this->_define_page_props();
634
+		$this->_current_page_view_url = add_query_arg(
635
+			['page' => $this->_current_page, 'action' => $this->_current_view],
636
+			$this->_admin_base_url
637
+		);
638
+		// set page configs
639
+		$this->_set_page_routes();
640
+		$this->_set_page_config();
641
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
642
+		if ($this->request->requestParamIsSet('wp_referer')) {
643
+			$wp_referer = $this->request->getRequestParam('wp_referer');
644
+			if ($wp_referer) {
645
+				$this->_default_route_query_args['wp_referer'] = $wp_referer;
646
+			}
647
+		}
648
+		// for CPT and other extended functionality.
649
+		// If there is an _extend_page_config_for_cpt
650
+		// then let's run that to modify all the various page configuration arrays.
651
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
652
+			$this->_extend_page_config_for_cpt();
653
+		}
654
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
655
+		$this->_page_routes = apply_filters(
656
+			'FHEE__' . $this->class_name . '__page_setup__page_routes',
657
+			$this->_page_routes,
658
+			$this
659
+		);
660
+		$this->_page_config = apply_filters(
661
+			'FHEE__' . $this->class_name . '__page_setup__page_config',
662
+			$this->_page_config,
663
+			$this
664
+		);
665
+		if ($this->base_class_name !== '') {
666
+			$this->_page_routes = apply_filters(
667
+				'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
668
+				$this->_page_routes,
669
+				$this
670
+			);
671
+			$this->_page_config = apply_filters(
672
+				'FHEE__' . $this->base_class_name . '__page_setup__page_config',
673
+				$this->_page_config,
674
+				$this
675
+			);
676
+		}
677
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
678
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
679
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
680
+			add_action(
681
+				'AHEE__EE_Admin_Page__route_admin_request',
682
+				[$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
683
+				10,
684
+				2
685
+			);
686
+		}
687
+		// next route only if routing enabled
688
+		if ($this->_routing && ! $this->request->isAjax()) {
689
+			$this->_verify_routes();
690
+			// next let's just check user_access and kill if no access
691
+			$this->check_user_access();
692
+			if ($this->_is_UI_request) {
693
+				// admin_init stuff - global, all views for this page class, specific view
694
+				add_action('admin_init', [$this, 'admin_init']);
695
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
696
+					add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
697
+				}
698
+			} else {
699
+				// hijack regular WP loading and route admin request immediately
700
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
701
+				$this->route_admin_request();
702
+			}
703
+		}
704
+	}
705
+
706
+
707
+	/**
708
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
709
+	 *
710
+	 * @return void
711
+	 * @throws EE_Error
712
+	 */
713
+	private function _do_other_page_hooks()
714
+	{
715
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
716
+		foreach ($registered_pages as $page) {
717
+			// now let's set up the file name and class that should be present
718
+			$classname = str_replace('.class.php', '', $page);
719
+			// autoloaders should take care of loading file
720
+			if (! class_exists($classname)) {
721
+				$error_msg[] = sprintf(
722
+					esc_html__(
723
+						'Something went wrong with loading the %s admin hooks page.',
724
+						'event_espresso'
725
+					),
726
+					$page
727
+				);
728
+				$error_msg[] = $error_msg[0]
729
+							   . "\r\n"
730
+							   . sprintf(
731
+								   esc_html__(
732
+									   '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',
733
+									   'event_espresso'
734
+								   ),
735
+								   $page,
736
+								   '<br />',
737
+								   '<strong>' . $classname . '</strong>'
738
+							   );
739
+				throw new EE_Error(implode('||', $error_msg));
740
+			}
741
+			// don't load the same class twice
742
+			static $loaded = [];
743
+			if (in_array($classname, $loaded, true)) {
744
+				continue;
745
+			}
746
+			$loaded[] = $classname;
747
+			// notice we are passing the instance of this class to the hook object.
748
+			$this->loader->getShared($classname, [$this]);
749
+		}
750
+	}
751
+
752
+
753
+	/**
754
+	 * @throws ReflectionException
755
+	 * @throws EE_Error
756
+	 */
757
+	public function load_page_dependencies()
758
+	{
759
+		try {
760
+			$this->_load_page_dependencies();
761
+		} catch (EE_Error $e) {
762
+			$e->get_error();
763
+		}
764
+	}
765
+
766
+
767
+	/**
768
+	 * load_page_dependencies
769
+	 * loads things specific to this page class when it's loaded.  Really helps with efficiency.
770
+	 *
771
+	 * @return void
772
+	 * @throws DomainException
773
+	 * @throws EE_Error
774
+	 * @throws InvalidArgumentException
775
+	 * @throws InvalidDataTypeException
776
+	 * @throws InvalidInterfaceException
777
+	 * @throws ReflectionException
778
+	 */
779
+	protected function _load_page_dependencies()
780
+	{
781
+		// let's set the current_screen and screen options to override what WP set
782
+		$this->_current_screen = get_current_screen();
783
+		// load admin_notices - global, page class, and view specific
784
+		add_action('admin_notices', [$this, 'admin_notices_global'], 5);
785
+		add_action('admin_notices', [$this, 'admin_notices']);
786
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
787
+			add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
788
+		}
789
+		// load network admin_notices - global, page class, and view specific
790
+		add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
791
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
792
+			add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
793
+		}
794
+		// this will save any per_page screen options if they are present
795
+		$this->_set_per_page_screen_options();
796
+		// setup list table properties
797
+		$this->_set_list_table();
798
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
799
+		// However in some cases the metaboxes will need to be added within a route handling callback.
800
+		add_action('add_meta_boxes', [$this, 'addRegisteredMetaBoxes'], 99);
801
+		// hack because promos admin was loading the edited promotion object in the metaboxes callback
802
+		// which should NOT be generated on non-UI requests like POST updates/inserts
803
+		if (
804
+			$this->class_name === 'Promotions_Admin_Page'
805
+			&& ($this->_req_action === 'edit' || $this->_req_action === 'create_new')
806
+		) {
807
+			$this->addRegisteredMetaBoxes();
808
+		}
809
+		$this->_add_screen_columns();
810
+		// add screen options - global, page child class, and view specific
811
+		$this->_add_global_screen_options();
812
+		$this->_add_screen_options();
813
+		$add_screen_options = "_add_screen_options_$this->_current_view";
814
+		if (method_exists($this, $add_screen_options)) {
815
+			$this->{$add_screen_options}();
816
+		}
817
+		// add help tab(s) - set via page_config and qtips.
818
+		$this->_add_help_tabs();
819
+		$this->_add_qtips();
820
+		// add feature_pointers - global, page child class, and view specific
821
+		$this->_add_feature_pointers();
822
+		$this->_add_global_feature_pointers();
823
+		$add_feature_pointer = "_add_feature_pointer_$this->_current_view";
824
+		if (method_exists($this, $add_feature_pointer)) {
825
+			$this->{$add_feature_pointer}();
826
+		}
827
+		// enqueue scripts/styles - global, page class, and view specific
828
+		add_action('admin_enqueue_scripts', [$this, 'admin_footer_scripts_eei18n_js_strings'], 1);
829
+		add_action('admin_enqueue_scripts', [$this, 'load_global_scripts_styles'], 5);
830
+		add_action('admin_enqueue_scripts', [$this, 'load_scripts_styles']);
831
+		if (method_exists($this, "load_scripts_styles_$this->_current_view")) {
832
+			add_action('admin_enqueue_scripts', [$this, "load_scripts_styles_$this->_current_view"], 15);
833
+		}
834
+		// admin_print_footer_scripts - global, page child class, and view specific.
835
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
836
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
837
+		// is a good use case. Notice the late priority we're giving these
838
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts_global'], 99);
839
+		add_action('admin_print_footer_scripts', [$this, 'admin_footer_scripts'], 100);
840
+		if (method_exists($this, "admin_footer_scripts_$this->_current_view")) {
841
+			add_action('admin_print_footer_scripts', [$this, "admin_footer_scripts_$this->_current_view"], 101);
842
+		}
843
+		// admin footer scripts
844
+		add_action('admin_footer', [$this, 'admin_footer_global'], 99);
845
+		add_action('admin_footer', [$this, 'admin_footer'], 100);
846
+		if (method_exists($this, "admin_footer_$this->_current_view")) {
847
+			add_action('admin_footer', [$this, "admin_footer_$this->_current_view"], 101);
848
+		}
849
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
850
+		// targeted hook
851
+		do_action(
852
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__$this->_req_action"
853
+		);
854
+	}
855
+
856
+
857
+	/**
858
+	 * _set_defaults
859
+	 * This sets some global defaults for class properties.
860
+	 */
861
+	private function _set_defaults()
862
+	{
863
+		// init template args
864
+		$this->set_template_args(
865
+			[
866
+				'admin_page_header'  => '',
867
+				'admin_page_content' => '',
868
+				'post_body_content'  => '',
869
+				'before_list_table'  => '',
870
+				'after_list_table'   => '',
871
+			]
872
+		);
873
+	}
874
+
875
+
876
+	/**
877
+	 * route_admin_request
878
+	 *
879
+	 * @return void
880
+	 * @throws InvalidArgumentException
881
+	 * @throws InvalidInterfaceException
882
+	 * @throws InvalidDataTypeException
883
+	 * @throws EE_Error
884
+	 * @throws ReflectionException
885
+	 * @throws Throwable
886
+	 * @see    _route_admin_request()
887
+	 */
888
+	public function route_admin_request()
889
+	{
890
+		try {
891
+			$this->_route_admin_request();
892
+		} catch (EE_Error $e) {
893
+			$e->get_error();
894
+		}
895
+	}
896
+
897
+
898
+	public function set_wp_page_slug($wp_page_slug)
899
+	{
900
+		$this->_wp_page_slug = $wp_page_slug;
901
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
902
+		if (is_network_admin()) {
903
+			$this->_wp_page_slug .= '-network';
904
+		}
905
+	}
906
+
907
+
908
+	/**
909
+	 * _verify_routes
910
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
911
+	 * we know if we need to drop out.
912
+	 *
913
+	 * @return bool
914
+	 * @throws EE_Error
915
+	 */
916
+	protected function _verify_routes(): bool
917
+	{
918
+		if (! $this->_current_page && ! $this->request->isAjax()) {
919
+			return false;
920
+		}
921
+		// check that the page_routes array is not empty
922
+		if (empty($this->_page_routes)) {
923
+			// user error msg
924
+			$error_msg = sprintf(
925
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
926
+				$this->_admin_page_title
927
+			);
928
+			// developer error msg
929
+			$error_msg .= '||' . $error_msg
930
+						  . esc_html__(
931
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
932
+							  'event_espresso'
933
+						  );
934
+			throw new EE_Error($error_msg);
935
+		}
936
+		// route 'editpost' routes to CPT 'edit' routes
937
+		$alt_edit_route = $this instanceof EE_Admin_Page_CPT ? $this->cpt_editpost_route : 'edit';
938
+		if (
939
+			$this->_req_action === 'editpost'
940
+			&& ! isset($this->_page_routes['editpost'])
941
+			&& isset($this->_page_routes[ $alt_edit_route ])
942
+		) {
943
+			$this->_req_action = $alt_edit_route;
944
+		}
945
+		// and that the requested page route exists
946
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
947
+			$this->_route        = $this->_page_routes[ $this->_req_action ];
948
+			$this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
949
+		} else {
950
+			// user error msg
951
+			$error_msg = sprintf(
952
+				esc_html__(
953
+					'The requested page route does not exist for the %s admin page.',
954
+					'event_espresso'
955
+				),
956
+				$this->_admin_page_title
957
+			);
958
+			// developer error msg
959
+			$error_msg .= '||' . $error_msg
960
+						  . sprintf(
961
+							  esc_html__(
962
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
963
+								  'event_espresso'
964
+							  ),
965
+							  $this->_req_action
966
+						  );
967
+			throw new EE_Error($error_msg);
968
+		}
969
+		// and that a default route exists
970
+		if (! array_key_exists('default', $this->_page_routes)) {
971
+			// user error msg
972
+			$error_msg = sprintf(
973
+				esc_html__(
974
+					'A default page route has not been set for the % admin page.',
975
+					'event_espresso'
976
+				),
977
+				$this->_admin_page_title
978
+			);
979
+			// developer error msg
980
+			$error_msg .= '||' . $error_msg
981
+						  . esc_html__(
982
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
983
+							  'event_espresso'
984
+						  );
985
+			throw new EE_Error($error_msg);
986
+		}
987
+
988
+		// first lets' catch if the UI request has EVER been set.
989
+		if ($this->_is_UI_request === null) {
990
+			// let's set if this is a UI request or not.
991
+			$this->_is_UI_request = ! $this->request->getRequestParam('noheader', false, DataType::BOOL);
992
+			// wait a minute... we might have a noheader in the route array
993
+			$this->_is_UI_request = ! (isset($this->_route['noheader']) && $this->_route['noheader'])
994
+				? $this->_is_UI_request
995
+				: false;
996
+		}
997
+		$this->_set_current_labels();
998
+		return true;
999
+	}
1000
+
1001
+
1002
+	/**
1003
+	 * this method simply verifies a given route and makes sure it's an actual route available for the loaded page
1004
+	 *
1005
+	 * @param string $route the route name we're verifying
1006
+	 * @return bool we'll throw an exception if this isn't a valid route.
1007
+	 * @throws EE_Error
1008
+	 */
1009
+	protected function _verify_route(string $route): bool
1010
+	{
1011
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
1012
+			return true;
1013
+		}
1014
+		// user error msg
1015
+		$error_msg = sprintf(
1016
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
1017
+			$this->_admin_page_title
1018
+		);
1019
+		// developer error msg
1020
+		$error_msg .= '||' . $error_msg
1021
+					  . sprintf(
1022
+						  esc_html__(
1023
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
1024
+							  'event_espresso'
1025
+						  ),
1026
+						  $route
1027
+					  );
1028
+		throw new EE_Error($error_msg);
1029
+	}
1030
+
1031
+
1032
+	/**
1033
+	 * perform nonce verification
1034
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
1035
+	 * using this method (and save retyping!)
1036
+	 *
1037
+	 * @param string $nonce     The nonce sent
1038
+	 * @param string $nonce_ref The nonce reference string (name0)
1039
+	 * @return void
1040
+	 * @throws EE_Error
1041
+	 * @throws InvalidArgumentException
1042
+	 * @throws InvalidDataTypeException
1043
+	 * @throws InvalidInterfaceException
1044
+	 */
1045
+	protected function _verify_nonce(string $nonce, string $nonce_ref)
1046
+	{
1047
+		// verify nonce against expected value
1048
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
1049
+			// these are not the droids you are looking for !!!
1050
+			$msg = sprintf(
1051
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
1052
+				'<a href="https://www.youtube.com/watch?v=56_S0WeTkzs">',
1053
+				'</a>'
1054
+			);
1055
+			if (WP_DEBUG) {
1056
+				$msg .= "\n  ";
1057
+				$msg .= sprintf(
1058
+					esc_html__(
1059
+						'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
1060
+						'event_espresso'
1061
+					),
1062
+					__CLASS__
1063
+				);
1064
+			}
1065
+			if (! $this->request->isAjax()) {
1066
+				wp_die($msg);
1067
+			}
1068
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1069
+			$this->_return_json();
1070
+		}
1071
+	}
1072
+
1073
+
1074
+	/**
1075
+	 * _route_admin_request()
1076
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
1077
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
1078
+	 * in the page routes and then will try to load the corresponding method.
1079
+	 *
1080
+	 * @return void
1081
+	 * @throws EE_Error
1082
+	 * @throws InvalidArgumentException
1083
+	 * @throws InvalidDataTypeException
1084
+	 * @throws InvalidInterfaceException
1085
+	 * @throws ReflectionException
1086
+	 * @throws Throwable
1087
+	 */
1088
+	protected function _route_admin_request()
1089
+	{
1090
+		if (! $this->_is_UI_request) {
1091
+			$this->_verify_routes();
1092
+		}
1093
+		$nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
1094
+		if ($this->_req_action !== 'default' && $nonce_check) {
1095
+			// set nonce from post data
1096
+			$nonce = $this->request->getRequestParam($this->_req_nonce, '');
1097
+			$this->_verify_nonce($nonce, $this->_req_nonce);
1098
+		}
1099
+		// set the nav_tabs array but ONLY if this is  UI_request
1100
+		if ($this->_is_UI_request) {
1101
+			$this->_set_nav_tabs();
1102
+		}
1103
+		// grab callback function
1104
+		$func = $this->_route['func'] ?? $this->_route;
1105
+		// check if callback has args
1106
+		$args = $this->_route['args'] ?? [];
1107
+
1108
+		// action right before calling route
1109
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1110
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1111
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1112
+		}
1113
+		// strip _wp_http_referer from the server REQUEST_URI
1114
+		// else it grows in length on every submission due to recursion,
1115
+		// ultimately causing a "Request-URI Too Large" error
1116
+		$this->request->unSetRequestParam('_wp_http_referer');
1117
+		$this->request->unSetServerParam('_wp_http_referer');
1118
+		$cleaner_request_uri = remove_query_arg(
1119
+			'_wp_http_referer',
1120
+			wp_unslash($this->request->getServerParam('REQUEST_URI'))
1121
+		);
1122
+		$this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1123
+		$this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1124
+		$route_callback = [];
1125
+		if (! empty($func)) {
1126
+			if (is_array($func) && is_callable($func)) {
1127
+				$route_callback = $func;
1128
+			} elseif (is_string($func)) {
1129
+				if (strpos($func, '::') !== false) {
1130
+					$route_callback = explode('::', $func);
1131
+				} elseif (method_exists($this, $func)) {
1132
+					$route_callback = [$this, $func];
1133
+				} else {
1134
+					$route_callback = $func;
1135
+				}
1136
+			}
1137
+			[$class, $method] = $route_callback;
1138
+			// is it neither a class method NOR a standalone function?
1139
+			if (! is_callable($route_callback)) {
1140
+				// user error msg
1141
+				$error_msg = esc_html__(
1142
+					'An error occurred. The  requested page route could not be found.',
1143
+					'event_espresso'
1144
+				);
1145
+				// developer error msg
1146
+				$error_msg .= '||';
1147
+				$error_msg .= sprintf(
1148
+					esc_html__(
1149
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1150
+						'event_espresso'
1151
+					),
1152
+					$method
1153
+				);
1154
+				throw new DomainException($error_msg);
1155
+			}
1156
+			if ($class !== $this && ! in_array($this, $args)) {
1157
+				// send along this admin page object for access by addons.
1158
+				$args['admin_page'] = $this;
1159
+			}
1160
+
1161
+			call_user_func_array($route_callback, $args);
1162
+		}
1163
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1164
+		// then we need to reset the routing properties to the new route.
1165
+		// 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.
1166
+		if (
1167
+			$this->_is_UI_request === false
1168
+			&& is_array($this->_route)
1169
+			&& ! empty($this->_route['headers_sent_route'])
1170
+		) {
1171
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1172
+		}
1173
+	}
1174
+
1175
+
1176
+	/**
1177
+	 * This method just allows the resetting of page properties in the case where a no headers
1178
+	 * route redirects to a headers route in its route config.
1179
+	 *
1180
+	 * @param string $new_route New (non header) route to redirect to.
1181
+	 * @return void
1182
+	 * @throws ReflectionException
1183
+	 * @throws InvalidArgumentException
1184
+	 * @throws InvalidInterfaceException
1185
+	 * @throws InvalidDataTypeException
1186
+	 * @throws EE_Error
1187
+	 * @throws Throwable
1188
+	 * @since   4.3.0
1189
+	 */
1190
+	protected function _reset_routing_properties(string $new_route)
1191
+	{
1192
+		$this->_is_UI_request = true;
1193
+		// now we set the current route to whatever the headers_sent_route is set at
1194
+		$this->request->setRequestParam('action', $new_route);
1195
+		// rerun page setup
1196
+		$this->_page_setup();
1197
+	}
1198
+
1199
+
1200
+	/**
1201
+	 * _add_query_arg
1202
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1203
+	 *(internally just uses EEH_URL's function with the same name)
1204
+	 *
1205
+	 * @param array  $args
1206
+	 * @param string $url
1207
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1208
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1209
+	 *                                        Example usage: If the current page is:
1210
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1211
+	 *                                        &action=default&event_id=20&month_range=March%202015
1212
+	 *                                        &_wpnonce=5467821
1213
+	 *                                        and you call:
1214
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1215
+	 *                                        array(
1216
+	 *                                        'action' => 'resend_something',
1217
+	 *                                        'page=>espresso_registrations'
1218
+	 *                                        ),
1219
+	 *                                        $some_url,
1220
+	 *                                        true
1221
+	 *                                        );
1222
+	 *                                        It will produce a URL in this structure:
1223
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1224
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1225
+	 *                                        month_range]=March%202015
1226
+	 * @param bool   $exclude_nonce           If true, the nonce will be excluded from the generated nonce.
1227
+	 * @param int    $context
1228
+	 * @return string
1229
+	 */
1230
+	public static function add_query_args_and_nonce(
1231
+		array $args = [],
1232
+		string $url = '',
1233
+		bool $sticky = false,
1234
+		bool $exclude_nonce = false,
1235
+		int $context = EEH_URL::CONTEXT_NONE
1236
+	): string {
1237
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1238
+		if ($sticky) {
1239
+			/** @var RequestInterface $request */
1240
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1241
+			$request->unSetRequestParams(['_wp_http_referer', 'wp_referer'], true);
1242
+			$request->unSetServerParam('_wp_http_referer', true);
1243
+			foreach ($request->requestParams() as $key => $value) {
1244
+				// do not add nonces
1245
+				if (strpos($key, 'nonce') !== false) {
1246
+					continue;
1247
+				}
1248
+				$args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1249
+			}
1250
+		}
1251
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce, $context);
1252
+	}
1253
+
1254
+
1255
+	/**
1256
+	 * This returns a generated link that will load the related help tab.
1257
+	 *
1258
+	 * @param string $help_tab_id the id for the connected help tab
1259
+	 * @param string $icon_style  (optional) include css class for the style you want to use for the help icon.
1260
+	 * @param string $help_text   (optional) send help text you want to use for the link if default not to be used
1261
+	 * @return string              generated link
1262
+	 * @uses EEH_Template::get_help_tab_link()
1263
+	 */
1264
+	protected function _get_help_tab_link(string $help_tab_id, string $icon_style = '', string $help_text = ''): string
1265
+	{
1266
+		return EEH_Template::get_help_tab_link(
1267
+			$help_tab_id,
1268
+			$this->page_slug,
1269
+			$this->_req_action,
1270
+			$icon_style,
1271
+			$help_text
1272
+		);
1273
+	}
1274
+
1275
+
1276
+	/**
1277
+	 * _add_help_tabs
1278
+	 * Note child classes define their help tabs within the page_config array.
1279
+	 *
1280
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1281
+	 * @return void
1282
+	 * @throws DomainException
1283
+	 * @throws EE_Error
1284
+	 * @throws ReflectionException
1285
+	 */
1286
+	protected function _add_help_tabs()
1287
+	{
1288
+		if (isset($this->_page_config[ $this->_req_action ])) {
1289
+			$config = $this->_page_config[ $this->_req_action ];
1290
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1291
+			if (is_array($config) && isset($config['help_sidebar'])) {
1292
+				// check that the callback given is valid
1293
+				if (! method_exists($this, $config['help_sidebar'])) {
1294
+					throw new EE_Error(
1295
+						sprintf(
1296
+							esc_html__(
1297
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Double check the spelling and make sure this method exists for the class %s',
1298
+								'event_espresso'
1299
+							),
1300
+							$config['help_sidebar'],
1301
+							$this->class_name
1302
+						)
1303
+					);
1304
+				}
1305
+				$content = apply_filters(
1306
+					'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1307
+					$this->{$config['help_sidebar']}()
1308
+				);
1309
+				$this->_current_screen->set_help_sidebar($content);
1310
+			}
1311
+			if (! isset($config['help_tabs'])) {
1312
+				return;
1313
+			} //no help tabs for this route
1314
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1315
+				// we're here so there ARE help tabs!
1316
+				// make sure we've got what we need
1317
+				if (! isset($cfg['title'])) {
1318
+					throw new EE_Error(
1319
+						esc_html__(
1320
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1321
+							'event_espresso'
1322
+						)
1323
+					);
1324
+				}
1325
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1326
+					throw new EE_Error(
1327
+						esc_html__(
1328
+							'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',
1329
+							'event_espresso'
1330
+						)
1331
+					);
1332
+				}
1333
+				// first priority goes to content.
1334
+				if (! empty($cfg['content'])) {
1335
+					$content = $cfg['content'];
1336
+					// second priority goes to filename
1337
+				} elseif (! empty($cfg['filename'])) {
1338
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1339
+					// 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)
1340
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1341
+															 . basename($this->_get_dir())
1342
+															 . '/help_tabs/'
1343
+															 . $cfg['filename']
1344
+															 . '.help_tab.php' : $file_path;
1345
+					// if file is STILL not readable then let's do an EE_Error so its more graceful than a fatal error.
1346
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1347
+						EE_Error::add_error(
1348
+							sprintf(
1349
+								esc_html__(
1350
+									'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',
1351
+									'event_espresso'
1352
+								),
1353
+								$tab_id,
1354
+								key($config),
1355
+								$file_path
1356
+							),
1357
+							__FILE__,
1358
+							__FUNCTION__,
1359
+							__LINE__
1360
+						);
1361
+						return;
1362
+					}
1363
+					$template_args['admin_page_obj'] = $this;
1364
+					$content                         = EEH_Template::display_template(
1365
+						$file_path,
1366
+						$template_args,
1367
+						true
1368
+					);
1369
+				} else {
1370
+					$content = '';
1371
+				}
1372
+				// check if callback is valid
1373
+				if (
1374
+					empty($content)
1375
+					&& (
1376
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1377
+					)
1378
+				) {
1379
+					EE_Error::add_error(
1380
+						sprintf(
1381
+							esc_html__(
1382
+								'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.',
1383
+								'event_espresso'
1384
+							),
1385
+							$cfg['title']
1386
+						),
1387
+						__FILE__,
1388
+						__FUNCTION__,
1389
+						__LINE__
1390
+					);
1391
+					return;
1392
+				}
1393
+				// setup config array for help tab method
1394
+				$id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1395
+				$_ht = [
1396
+					'id'       => $id,
1397
+					'title'    => $cfg['title'],
1398
+					'callback' => isset($cfg['callback']) && empty($content) ? [$this, $cfg['callback']] : null,
1399
+					'content'  => $content,
1400
+				];
1401
+				$this->_current_screen->add_help_tab($_ht);
1402
+			}
1403
+		}
1404
+	}
1405
+
1406
+
1407
+	/**
1408
+	 * This simply sets up any qtips that have been defined in the page config
1409
+	 *
1410
+	 * @return void
1411
+	 * @throws ReflectionException
1412
+	 * @throws EE_Error
1413
+	 */
1414
+	protected function _add_qtips()
1415
+	{
1416
+		if (isset($this->_route_config['qtips'])) {
1417
+			$qtips = (array) $this->_route_config['qtips'];
1418
+			// load qtip loader
1419
+			$path = [
1420
+				$this->_get_dir() . '/qtips/',
1421
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1422
+			];
1423
+			EEH_Qtip_Loader::instance()->register($qtips, $path);
1424
+		}
1425
+	}
1426
+
1427
+
1428
+	/**
1429
+	 * _set_nav_tabs
1430
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1431
+	 * wish to add additional tabs or modify accordingly.
1432
+	 *
1433
+	 * @return void
1434
+	 * @throws InvalidArgumentException
1435
+	 * @throws InvalidInterfaceException
1436
+	 * @throws InvalidDataTypeException
1437
+	 */
1438
+	protected function _set_nav_tabs()
1439
+	{
1440
+		$i        = 0;
1441
+		$only_tab = count($this->_page_config) < 2;
1442
+		foreach ($this->_page_config as $slug => $config) {
1443
+			if (! is_array($config) || empty($config['nav'])) {
1444
+				continue;
1445
+			}
1446
+			// no nav tab for this config
1447
+			// check for persistent flag
1448
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1449
+				// nav tab is only to appear when route requested.
1450
+				continue;
1451
+			}
1452
+			if (! $this->check_user_access($slug, true)) {
1453
+				// no nav tab because current user does not have access.
1454
+				continue;
1455
+			}
1456
+			$css_class = $config['css_class'] ?? '';
1457
+			$css_class .= $only_tab ? ' ee-only-tab' : '';
1458
+			$css_class .= " ee-nav-tab__$slug";
1459
+
1460
+			$this->_nav_tabs[ $slug ] = [
1461
+				'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1462
+					['action' => $slug],
1463
+					$this->_admin_base_url
1464
+				),
1465
+				'link_text' => $this->navTabLabel($config['nav'], $slug),
1466
+				'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1467
+				'order'     => $config['nav']['order'] ?? $i,
1468
+			];
1469
+			$i++;
1470
+		}
1471
+		// if $this->_nav_tabs is empty then lets set the default
1472
+		if (empty($this->_nav_tabs)) {
1473
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1474
+				'url'       => $this->_admin_base_url,
1475
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1476
+				'css_class' => 'nav-tab-active',
1477
+				'order'     => 10,
1478
+			];
1479
+		}
1480
+		// now let's sort the tabs according to order
1481
+		usort($this->_nav_tabs, [$this, '_sort_nav_tabs']);
1482
+	}
1483
+
1484
+
1485
+	private function navTabLabel(array $nav_tab, string $slug): string
1486
+	{
1487
+		$label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1488
+		$icon  = $nav_tab['icon'] ?? null;
1489
+		$icon  = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1490
+		return '
1491 1491
             <span class="ee-admin-screen-tab__label">
1492 1492
                 ' . $icon . '
1493 1493
                 <span class="ee-nav-label__text">' . $label . '</span>
1494 1494
             </span>';
1495
-    }
1496
-
1497
-
1498
-    /**
1499
-     * _set_current_labels
1500
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1501
-     * property array
1502
-     *
1503
-     * @return void
1504
-     */
1505
-    private function _set_current_labels()
1506
-    {
1507
-        if (isset($this->_route_config['labels'])) {
1508
-            foreach ($this->_route_config['labels'] as $label => $text) {
1509
-                if (is_array($text)) {
1510
-                    foreach ($text as $sublabel => $subtext) {
1511
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1512
-                    }
1513
-                } else {
1514
-                    $this->_labels[ $label ] = $text;
1515
-                }
1516
-            }
1517
-        }
1518
-    }
1519
-
1520
-
1521
-    /**
1522
-     *        verifies user access for this admin page
1523
-     *
1524
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1525
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1526
-     *                               return false if verify fail.
1527
-     * @return bool
1528
-     * @throws InvalidArgumentException
1529
-     * @throws InvalidDataTypeException
1530
-     * @throws InvalidInterfaceException
1531
-     */
1532
-    public function check_user_access(string $route_to_check = '', bool $verify_only = false): bool
1533
-    {
1534
-        // if no route_to_check is passed in then use the current route set via _req_action
1535
-        $action = $route_to_check ?: $this->_req_action;
1536
-        $capability = ! empty($this->_page_routes[ $action ]['capability'])
1537
-            ? $this->_page_routes[ $action ]['capability']
1538
-            : null;
1539
-
1540
-        if (empty($capability)) {
1541
-            $capability = empty($route_to_check) && ! empty($this->_route['capability'])
1542
-                ? $this->_route['capability']
1543
-                : 'manage_options';
1544
-        }
1545
-
1546
-        $id = $this->_route['obj_id'] ?? 0;
1547
-
1548
-        if (
1549
-            ! $this->request->isAjax()
1550
-            && (
1551
-                ! function_exists('is_admin')
1552
-                || ! $this->capabilities->current_user_can($capability, "{$this->page_slug}_$route_to_check", $id)
1553
-            )
1554
-        ) {
1555
-            if ($verify_only) {
1556
-                return false;
1557
-            }
1558
-            if (is_user_logged_in()) {
1559
-                wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1560
-            }
1561
-            return false;
1562
-        }
1563
-        return true;
1564
-    }
1565
-
1566
-
1567
-    /**
1568
-     * @param string                 $box_id
1569
-     * @param string                 $title
1570
-     * @param callable|string|null   $callback
1571
-     * @param string|array|WP_Screen $screen
1572
-     * @param string                 $context       Post edit screen contexts include 'normal', 'side', and 'advanced'.
1573
-     *                                              Comments screen contexts include 'normal' and 'side'.
1574
-     *                                              Menus meta boxes (accordion sections) all use the 'side' context.
1575
-     * @param string                 $priority      Accepts 'high', 'core', 'default', or 'low'.
1576
-     * @param array|null             $callback_args
1577
-     */
1578
-    protected function addMetaBox(
1579
-        string $box_id,
1580
-        string $title,
1581
-        $callback,
1582
-        $screen,
1583
-        string $context = 'normal',
1584
-        string $priority = 'default',
1585
-        ?array $callback_args = null
1586
-    ) {
1587
-        if (! (is_callable($callback) || ! function_exists($callback))) {
1588
-            return;
1589
-        }
1590
-
1591
-        add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1592
-        add_filter(
1593
-            "postbox_classes_{$this->_wp_page_slug}_$box_id",
1594
-            function ($classes) {
1595
-                $classes[] = 'ee-admin-container';
1596
-                return $classes;
1597
-            }
1598
-        );
1599
-    }
1600
-
1601
-
1602
-    /**
1603
-     * admin_init_global
1604
-     * This runs all the code that we want executed within the WP admin_init hook.
1605
-     * This method executes for ALL EE Admin pages.
1606
-     *
1607
-     * @return void
1608
-     */
1609
-    public function admin_init_global()
1610
-    {
1611
-    }
1612
-
1613
-
1614
-    /**
1615
-     * wp_loaded_global
1616
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1617
-     * EE_Admin page and will execute on every EE Admin Page load
1618
-     *
1619
-     * @return void
1620
-     */
1621
-    public function wp_loaded()
1622
-    {
1623
-    }
1624
-
1625
-
1626
-    /**
1627
-     * admin_notices
1628
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1629
-     * ALL EE_Admin pages.
1630
-     *
1631
-     * @return void
1632
-     */
1633
-    public function admin_notices_global()
1634
-    {
1635
-        $this->_display_no_javascript_warning();
1636
-        $this->_display_espresso_notices();
1637
-    }
1638
-
1639
-
1640
-    public function network_admin_notices_global()
1641
-    {
1642
-        $this->_display_no_javascript_warning();
1643
-        $this->_display_espresso_notices();
1644
-    }
1645
-
1646
-
1647
-    /**
1648
-     * admin_footer_scripts_global
1649
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1650
-     * will apply on ALL EE_Admin pages.
1651
-     *
1652
-     * @return void
1653
-     */
1654
-    public function admin_footer_scripts_global()
1655
-    {
1656
-        $this->_add_admin_page_ajax_loading_img();
1657
-        $this->_add_admin_page_overlay();
1658
-        // if metaboxes are present we need to add the nonce field
1659
-        if (
1660
-            isset($this->_route_config['metaboxes'])
1661
-            || isset($this->_route_config['list_table'])
1662
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1663
-        ) {
1664
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1665
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1666
-        }
1667
-    }
1668
-
1669
-
1670
-    /**
1671
-     * admin_footer_global
1672
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1673
-     * This particular method will apply on ALL EE_Admin Pages.
1674
-     *
1675
-     * @return void
1676
-     */
1677
-    public function admin_footer_global()
1678
-    {
1679
-        // dialog container for dialog helper
1680
-        echo '
1495
+	}
1496
+
1497
+
1498
+	/**
1499
+	 * _set_current_labels
1500
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1501
+	 * property array
1502
+	 *
1503
+	 * @return void
1504
+	 */
1505
+	private function _set_current_labels()
1506
+	{
1507
+		if (isset($this->_route_config['labels'])) {
1508
+			foreach ($this->_route_config['labels'] as $label => $text) {
1509
+				if (is_array($text)) {
1510
+					foreach ($text as $sublabel => $subtext) {
1511
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1512
+					}
1513
+				} else {
1514
+					$this->_labels[ $label ] = $text;
1515
+				}
1516
+			}
1517
+		}
1518
+	}
1519
+
1520
+
1521
+	/**
1522
+	 *        verifies user access for this admin page
1523
+	 *
1524
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1525
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1526
+	 *                               return false if verify fail.
1527
+	 * @return bool
1528
+	 * @throws InvalidArgumentException
1529
+	 * @throws InvalidDataTypeException
1530
+	 * @throws InvalidInterfaceException
1531
+	 */
1532
+	public function check_user_access(string $route_to_check = '', bool $verify_only = false): bool
1533
+	{
1534
+		// if no route_to_check is passed in then use the current route set via _req_action
1535
+		$action = $route_to_check ?: $this->_req_action;
1536
+		$capability = ! empty($this->_page_routes[ $action ]['capability'])
1537
+			? $this->_page_routes[ $action ]['capability']
1538
+			: null;
1539
+
1540
+		if (empty($capability)) {
1541
+			$capability = empty($route_to_check) && ! empty($this->_route['capability'])
1542
+				? $this->_route['capability']
1543
+				: 'manage_options';
1544
+		}
1545
+
1546
+		$id = $this->_route['obj_id'] ?? 0;
1547
+
1548
+		if (
1549
+			! $this->request->isAjax()
1550
+			&& (
1551
+				! function_exists('is_admin')
1552
+				|| ! $this->capabilities->current_user_can($capability, "{$this->page_slug}_$route_to_check", $id)
1553
+			)
1554
+		) {
1555
+			if ($verify_only) {
1556
+				return false;
1557
+			}
1558
+			if (is_user_logged_in()) {
1559
+				wp_die(esc_html__('You do not have access to this route.', 'event_espresso'));
1560
+			}
1561
+			return false;
1562
+		}
1563
+		return true;
1564
+	}
1565
+
1566
+
1567
+	/**
1568
+	 * @param string                 $box_id
1569
+	 * @param string                 $title
1570
+	 * @param callable|string|null   $callback
1571
+	 * @param string|array|WP_Screen $screen
1572
+	 * @param string                 $context       Post edit screen contexts include 'normal', 'side', and 'advanced'.
1573
+	 *                                              Comments screen contexts include 'normal' and 'side'.
1574
+	 *                                              Menus meta boxes (accordion sections) all use the 'side' context.
1575
+	 * @param string                 $priority      Accepts 'high', 'core', 'default', or 'low'.
1576
+	 * @param array|null             $callback_args
1577
+	 */
1578
+	protected function addMetaBox(
1579
+		string $box_id,
1580
+		string $title,
1581
+		$callback,
1582
+		$screen,
1583
+		string $context = 'normal',
1584
+		string $priority = 'default',
1585
+		?array $callback_args = null
1586
+	) {
1587
+		if (! (is_callable($callback) || ! function_exists($callback))) {
1588
+			return;
1589
+		}
1590
+
1591
+		add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1592
+		add_filter(
1593
+			"postbox_classes_{$this->_wp_page_slug}_$box_id",
1594
+			function ($classes) {
1595
+				$classes[] = 'ee-admin-container';
1596
+				return $classes;
1597
+			}
1598
+		);
1599
+	}
1600
+
1601
+
1602
+	/**
1603
+	 * admin_init_global
1604
+	 * This runs all the code that we want executed within the WP admin_init hook.
1605
+	 * This method executes for ALL EE Admin pages.
1606
+	 *
1607
+	 * @return void
1608
+	 */
1609
+	public function admin_init_global()
1610
+	{
1611
+	}
1612
+
1613
+
1614
+	/**
1615
+	 * wp_loaded_global
1616
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1617
+	 * EE_Admin page and will execute on every EE Admin Page load
1618
+	 *
1619
+	 * @return void
1620
+	 */
1621
+	public function wp_loaded()
1622
+	{
1623
+	}
1624
+
1625
+
1626
+	/**
1627
+	 * admin_notices
1628
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1629
+	 * ALL EE_Admin pages.
1630
+	 *
1631
+	 * @return void
1632
+	 */
1633
+	public function admin_notices_global()
1634
+	{
1635
+		$this->_display_no_javascript_warning();
1636
+		$this->_display_espresso_notices();
1637
+	}
1638
+
1639
+
1640
+	public function network_admin_notices_global()
1641
+	{
1642
+		$this->_display_no_javascript_warning();
1643
+		$this->_display_espresso_notices();
1644
+	}
1645
+
1646
+
1647
+	/**
1648
+	 * admin_footer_scripts_global
1649
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1650
+	 * will apply on ALL EE_Admin pages.
1651
+	 *
1652
+	 * @return void
1653
+	 */
1654
+	public function admin_footer_scripts_global()
1655
+	{
1656
+		$this->_add_admin_page_ajax_loading_img();
1657
+		$this->_add_admin_page_overlay();
1658
+		// if metaboxes are present we need to add the nonce field
1659
+		if (
1660
+			isset($this->_route_config['metaboxes'])
1661
+			|| isset($this->_route_config['list_table'])
1662
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1663
+		) {
1664
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1665
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1666
+		}
1667
+	}
1668
+
1669
+
1670
+	/**
1671
+	 * admin_footer_global
1672
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1673
+	 * This particular method will apply on ALL EE_Admin Pages.
1674
+	 *
1675
+	 * @return void
1676
+	 */
1677
+	public function admin_footer_global()
1678
+	{
1679
+		// dialog container for dialog helper
1680
+		echo '
1681 1681
         <div class="ee-admin-dialog-container auto-hide hidden">
1682 1682
             <div class="ee-notices"></div>
1683 1683
             <div class="ee-admin-dialog-container-inner-content"></div>
1684 1684
         </div>
1685 1685
         <span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>
1686 1686
         <input type="hidden" id="espresso_admin_current_page" value="' . esc_attr($this->_current_page) . '"/>';
1687
-    }
1688
-
1689
-
1690
-    /**
1691
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1692
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1693
-     * help popups then in your templates or your content you set "triggers" for the content using the
1694
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1695
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1696
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1697
-     * for the
1698
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1699
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1700
-     *    'help_trigger_id' => array(
1701
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1702
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1703
-     *    )
1704
-     * );
1705
-     * Then the EE_Admin_Parent will take care of making sure that is set up properly on the correct route.
1706
-     *
1707
-     * @param array $help_array
1708
-     * @param bool  $display
1709
-     * @return string content
1710
-     * @throws DomainException
1711
-     * @throws EE_Error
1712
-     */
1713
-    protected function _set_help_popup_content(array $help_array = [], bool $display = false): string
1714
-    {
1715
-        $content    = '';
1716
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1717
-        // loop through the array and setup content
1718
-        foreach ($help_array as $trigger => $help) {
1719
-            // make sure the array is set up properly
1720
-            if (! isset($help['title'], $help['content'])) {
1721
-                throw new EE_Error(
1722
-                    esc_html__(
1723
-                        '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',
1724
-                        'event_espresso'
1725
-                    )
1726
-                );
1727
-            }
1728
-            // we're good so let's set up the template vars and then assign parsed template content to our content.
1729
-            $template_args = [
1730
-                'help_popup_id'      => $trigger,
1731
-                'help_popup_title'   => $help['title'],
1732
-                'help_popup_content' => $help['content'],
1733
-            ];
1734
-            $content       .= EEH_Template::display_template(
1735
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1736
-                $template_args,
1737
-                true
1738
-            );
1739
-        }
1740
-        if ($display) {
1741
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1742
-            return '';
1743
-        }
1744
-        return $content;
1745
-    }
1746
-
1747
-
1748
-    /**
1749
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1750
-     *
1751
-     * @return array properly formatted array for help popup content
1752
-     * @throws EE_Error
1753
-     */
1754
-    private function _get_help_content(): array
1755
-    {
1756
-        // what is the method we're looking for?
1757
-        $method_name = '_help_popup_content_' . $this->_req_action;
1758
-        // if method doesn't exist let's get out.
1759
-        if (! method_exists($this, $method_name)) {
1760
-            return [];
1761
-        }
1762
-        // k we're good to go let's retrieve the help array
1763
-        $help_array = $this->{$method_name}();
1764
-        // make sure we've got an array!
1765
-        if (! is_array($help_array)) {
1766
-            throw new EE_Error(
1767
-                esc_html__(
1768
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1769
-                    'event_espresso'
1770
-                )
1771
-            );
1772
-        }
1773
-        return $help_array;
1774
-    }
1775
-
1776
-
1777
-    /**
1778
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1779
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1780
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1781
-     *
1782
-     * @param string $trigger_id reference for retrieving the trigger content for the popup
1783
-     * @param bool   $display    if false then we return the trigger string
1784
-     * @param array  $dimensions an array of dimensions for the box (array(h,w))
1785
-     * @return string
1786
-     * @throws DomainException
1787
-     * @throws EE_Error
1788
-     */
1789
-    protected function _set_help_trigger(string $trigger_id, bool $display = true, array $dimensions = ['400', '640'])
1790
-    {
1791
-        if ($this->request->isAjax()) {
1792
-            return '';
1793
-        }
1794
-        // 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
1795
-        $help_array   = $this->_get_help_content();
1796
-        $help_content = '';
1797
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1798
-            $help_array[ $trigger_id ] = [
1799
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1800
-                'content' => esc_html__(
1801
-                    '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.)',
1802
-                    'event_espresso'
1803
-                ),
1804
-            ];
1805
-            $help_content              = $this->_set_help_popup_content($help_array);
1806
-        }
1807
-        $height   = esc_attr($dimensions[0]) ?? 400;
1808
-        $width    = esc_attr($dimensions[1]) ?? 640;
1809
-        $inlineId = esc_attr($trigger_id);
1810
-        // let's setup the trigger
1811
-        $content = "
1687
+	}
1688
+
1689
+
1690
+	/**
1691
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1692
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1693
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1694
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1695
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1696
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1697
+	 * for the
1698
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1699
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1700
+	 *    'help_trigger_id' => array(
1701
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1702
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1703
+	 *    )
1704
+	 * );
1705
+	 * Then the EE_Admin_Parent will take care of making sure that is set up properly on the correct route.
1706
+	 *
1707
+	 * @param array $help_array
1708
+	 * @param bool  $display
1709
+	 * @return string content
1710
+	 * @throws DomainException
1711
+	 * @throws EE_Error
1712
+	 */
1713
+	protected function _set_help_popup_content(array $help_array = [], bool $display = false): string
1714
+	{
1715
+		$content    = '';
1716
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1717
+		// loop through the array and setup content
1718
+		foreach ($help_array as $trigger => $help) {
1719
+			// make sure the array is set up properly
1720
+			if (! isset($help['title'], $help['content'])) {
1721
+				throw new EE_Error(
1722
+					esc_html__(
1723
+						'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',
1724
+						'event_espresso'
1725
+					)
1726
+				);
1727
+			}
1728
+			// we're good so let's set up the template vars and then assign parsed template content to our content.
1729
+			$template_args = [
1730
+				'help_popup_id'      => $trigger,
1731
+				'help_popup_title'   => $help['title'],
1732
+				'help_popup_content' => $help['content'],
1733
+			];
1734
+			$content       .= EEH_Template::display_template(
1735
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1736
+				$template_args,
1737
+				true
1738
+			);
1739
+		}
1740
+		if ($display) {
1741
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1742
+			return '';
1743
+		}
1744
+		return $content;
1745
+	}
1746
+
1747
+
1748
+	/**
1749
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1750
+	 *
1751
+	 * @return array properly formatted array for help popup content
1752
+	 * @throws EE_Error
1753
+	 */
1754
+	private function _get_help_content(): array
1755
+	{
1756
+		// what is the method we're looking for?
1757
+		$method_name = '_help_popup_content_' . $this->_req_action;
1758
+		// if method doesn't exist let's get out.
1759
+		if (! method_exists($this, $method_name)) {
1760
+			return [];
1761
+		}
1762
+		// k we're good to go let's retrieve the help array
1763
+		$help_array = $this->{$method_name}();
1764
+		// make sure we've got an array!
1765
+		if (! is_array($help_array)) {
1766
+			throw new EE_Error(
1767
+				esc_html__(
1768
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1769
+					'event_espresso'
1770
+				)
1771
+			);
1772
+		}
1773
+		return $help_array;
1774
+	}
1775
+
1776
+
1777
+	/**
1778
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1779
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1780
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1781
+	 *
1782
+	 * @param string $trigger_id reference for retrieving the trigger content for the popup
1783
+	 * @param bool   $display    if false then we return the trigger string
1784
+	 * @param array  $dimensions an array of dimensions for the box (array(h,w))
1785
+	 * @return string
1786
+	 * @throws DomainException
1787
+	 * @throws EE_Error
1788
+	 */
1789
+	protected function _set_help_trigger(string $trigger_id, bool $display = true, array $dimensions = ['400', '640'])
1790
+	{
1791
+		if ($this->request->isAjax()) {
1792
+			return '';
1793
+		}
1794
+		// 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
1795
+		$help_array   = $this->_get_help_content();
1796
+		$help_content = '';
1797
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1798
+			$help_array[ $trigger_id ] = [
1799
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1800
+				'content' => esc_html__(
1801
+					'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.)',
1802
+					'event_espresso'
1803
+				),
1804
+			];
1805
+			$help_content              = $this->_set_help_popup_content($help_array);
1806
+		}
1807
+		$height   = esc_attr($dimensions[0]) ?? 400;
1808
+		$width    = esc_attr($dimensions[1]) ?? 640;
1809
+		$inlineId = esc_attr($trigger_id);
1810
+		// let's setup the trigger
1811
+		$content = "
1812 1812
         <a class='ee-dialog' href='?height=$height&width=$width&inlineId=$inlineId' target='_blank'>
1813 1813
             <span class='question ee-help-popup-question'></span>
1814 1814
         </a>";
1815
-        $content .= $help_content;
1816
-        if ($display) {
1817
-            echo wp_kses($content, AllowedTags::getWithFormTags());
1818
-            return '';
1819
-        }
1820
-        return $content;
1821
-    }
1822
-
1823
-
1824
-    /**
1825
-     * _add_global_screen_options
1826
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1827
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1828
-     *
1829
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1830
-     *         see also WP_Screen object documents...
1831
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1832
-     * @abstract
1833
-     * @return void
1834
-     */
1835
-    private function _add_global_screen_options()
1836
-    {
1837
-    }
1838
-
1839
-
1840
-    /**
1841
-     * _add_global_feature_pointers
1842
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1843
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1844
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1845
-     *
1846
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (it's a final class so can't be
1847
-     *         extended) also see:
1848
-     * @link   http://eamann.com/tech/wordpress-portland/
1849
-     * @abstract
1850
-     * @return void
1851
-     */
1852
-    private function _add_global_feature_pointers()
1853
-    {
1854
-    }
1855
-
1856
-
1857
-    /**
1858
-     * load_global_scripts_styles
1859
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1860
-     *
1861
-     * @return void
1862
-     */
1863
-    public function load_global_scripts_styles()
1864
-    {
1865
-        // add debugging styles
1866
-        if (WP_DEBUG) {
1867
-            add_action('admin_head', [$this, 'add_xdebug_style']);
1868
-        }
1869
-        // taking care of metaboxes
1870
-        if (
1871
-            empty($this->_cpt_route)
1872
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1873
-        ) {
1874
-            wp_enqueue_script('dashboard');
1875
-        }
1876
-
1877
-        wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1878
-        wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1879
-        // LOCALIZED DATA
1880
-        // localize script for ajax lazy loading
1881
-        wp_localize_script(
1882
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1883
-            'eeLazyLoadingContainers',
1884
-            apply_filters(
1885
-                'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1886
-                ['espresso_news_post_box_content']
1887
-            )
1888
-        );
1889
-        StatusChangeNotice::loadAssets();
1890
-
1891
-        add_filter(
1892
-            'admin_body_class',
1893
-            function ($classes) {
1894
-                if (strpos($classes, 'espresso-admin') === false) {
1895
-                    $classes .= ' espresso-admin';
1896
-                }
1897
-                return $classes;
1898
-            }
1899
-        );
1900
-    }
1901
-
1902
-
1903
-    /**
1904
-     *        admin_footer_scripts_eei18n_js_strings
1905
-     *
1906
-     * @return        void
1907
-     */
1908
-    public function admin_footer_scripts_eei18n_js_strings()
1909
-    {
1910
-        EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1911
-            __(
1912
-                '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!!!',
1913
-                'event_espresso'
1914
-            )
1915
-        );
1916
-        // now add months and days of the week
1917
-        EE_Registry::$i18n_js_strings['January']   = wp_strip_all_tags(__('January', 'event_espresso'));
1918
-        EE_Registry::$i18n_js_strings['February']  = wp_strip_all_tags(__('February', 'event_espresso'));
1919
-        EE_Registry::$i18n_js_strings['March']     = wp_strip_all_tags(__('March', 'event_espresso'));
1920
-        EE_Registry::$i18n_js_strings['April']     = wp_strip_all_tags(__('April', 'event_espresso'));
1921
-        EE_Registry::$i18n_js_strings['May']       = wp_strip_all_tags(__('May', 'event_espresso'));
1922
-        EE_Registry::$i18n_js_strings['June']      = wp_strip_all_tags(__('June', 'event_espresso'));
1923
-        EE_Registry::$i18n_js_strings['July']      = wp_strip_all_tags(__('July', 'event_espresso'));
1924
-        EE_Registry::$i18n_js_strings['August']    = wp_strip_all_tags(__('August', 'event_espresso'));
1925
-        EE_Registry::$i18n_js_strings['September'] = wp_strip_all_tags(__('September', 'event_espresso'));
1926
-        EE_Registry::$i18n_js_strings['October']   = wp_strip_all_tags(__('October', 'event_espresso'));
1927
-        EE_Registry::$i18n_js_strings['November']  = wp_strip_all_tags(__('November', 'event_espresso'));
1928
-        EE_Registry::$i18n_js_strings['December']  = wp_strip_all_tags(__('December', 'event_espresso'));
1929
-        EE_Registry::$i18n_js_strings['Jan']       = wp_strip_all_tags(__('Jan', 'event_espresso'));
1930
-        EE_Registry::$i18n_js_strings['Feb']       = wp_strip_all_tags(__('Feb', 'event_espresso'));
1931
-        EE_Registry::$i18n_js_strings['Mar']       = wp_strip_all_tags(__('Mar', 'event_espresso'));
1932
-        EE_Registry::$i18n_js_strings['Apr']       = wp_strip_all_tags(__('Apr', 'event_espresso'));
1933
-        EE_Registry::$i18n_js_strings['May']       = wp_strip_all_tags(__('May', 'event_espresso'));
1934
-        EE_Registry::$i18n_js_strings['Jun']       = wp_strip_all_tags(__('Jun', 'event_espresso'));
1935
-        EE_Registry::$i18n_js_strings['Jul']       = wp_strip_all_tags(__('Jul', 'event_espresso'));
1936
-        EE_Registry::$i18n_js_strings['Aug']       = wp_strip_all_tags(__('Aug', 'event_espresso'));
1937
-        EE_Registry::$i18n_js_strings['Sep']       = wp_strip_all_tags(__('Sep', 'event_espresso'));
1938
-        EE_Registry::$i18n_js_strings['Oct']       = wp_strip_all_tags(__('Oct', 'event_espresso'));
1939
-        EE_Registry::$i18n_js_strings['Nov']       = wp_strip_all_tags(__('Nov', 'event_espresso'));
1940
-        EE_Registry::$i18n_js_strings['Dec']       = wp_strip_all_tags(__('Dec', 'event_espresso'));
1941
-        EE_Registry::$i18n_js_strings['Sunday']    = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1942
-        EE_Registry::$i18n_js_strings['Monday']    = wp_strip_all_tags(__('Monday', 'event_espresso'));
1943
-        EE_Registry::$i18n_js_strings['Tuesday']   = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1944
-        EE_Registry::$i18n_js_strings['Wednesday'] = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1945
-        EE_Registry::$i18n_js_strings['Thursday']  = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1946
-        EE_Registry::$i18n_js_strings['Friday']    = wp_strip_all_tags(__('Friday', 'event_espresso'));
1947
-        EE_Registry::$i18n_js_strings['Saturday']  = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1948
-        EE_Registry::$i18n_js_strings['Sun']       = wp_strip_all_tags(__('Sun', 'event_espresso'));
1949
-        EE_Registry::$i18n_js_strings['Mon']       = wp_strip_all_tags(__('Mon', 'event_espresso'));
1950
-        EE_Registry::$i18n_js_strings['Tue']       = wp_strip_all_tags(__('Tue', 'event_espresso'));
1951
-        EE_Registry::$i18n_js_strings['Wed']       = wp_strip_all_tags(__('Wed', 'event_espresso'));
1952
-        EE_Registry::$i18n_js_strings['Thu']       = wp_strip_all_tags(__('Thu', 'event_espresso'));
1953
-        EE_Registry::$i18n_js_strings['Fri']       = wp_strip_all_tags(__('Fri', 'event_espresso'));
1954
-        EE_Registry::$i18n_js_strings['Sat']       = wp_strip_all_tags(__('Sat', 'event_espresso'));
1955
-    }
1956
-
1957
-
1958
-    /**
1959
-     *        load enhanced xdebug styles for ppl with failing eyesight
1960
-     *
1961
-     * @return        void
1962
-     */
1963
-    public function add_xdebug_style()
1964
-    {
1965
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1966
-    }
1967
-
1968
-
1969
-    /************************/
1970
-    /** LIST TABLE METHODS **/
1971
-    /************************/
1972
-    /**
1973
-     * this sets up the list table if the current view requires it.
1974
-     *
1975
-     * @return void
1976
-     * @throws EE_Error
1977
-     * @throws InvalidArgumentException
1978
-     * @throws InvalidDataTypeException
1979
-     * @throws InvalidInterfaceException
1980
-     */
1981
-    protected function _set_list_table()
1982
-    {
1983
-        // first is this a list_table view?
1984
-        if (! isset($this->_route_config['list_table'])) {
1985
-            return;
1986
-        } //not a list_table view so get out.
1987
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
1988
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
1989
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1990
-            // user error msg
1991
-            $error_msg = esc_html__(
1992
-                'An error occurred. The requested list table views could not be found.',
1993
-                'event_espresso'
1994
-            );
1995
-            // developer error msg
1996
-            $error_msg .= '||'
1997
-                          . sprintf(
1998
-                              esc_html__(
1999
-                                  '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.',
2000
-                                  'event_espresso'
2001
-                              ),
2002
-                              $this->_req_action,
2003
-                              $list_table_view
2004
-                          );
2005
-            throw new EE_Error($error_msg);
2006
-        }
2007
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2008
-        $this->_views = apply_filters(
2009
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2010
-            $this->_views
2011
-        );
2012
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2013
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2014
-        $this->_set_list_table_view();
2015
-        $this->_set_list_table_object();
2016
-    }
2017
-
2018
-
2019
-    /**
2020
-     * set current view for List Table
2021
-     *
2022
-     * @return void
2023
-     */
2024
-    protected function _set_list_table_view()
2025
-    {
2026
-        $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2027
-        $status      = $this->request->getRequestParam('status', null, DataType::KEY);
2028
-        $this->_view = $status && array_key_exists($status, $this->_views)
2029
-            ? $status
2030
-            : $this->_view;
2031
-    }
2032
-
2033
-
2034
-    /**
2035
-     * _set_list_table_object
2036
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2037
-     *
2038
-     * @throws InvalidInterfaceException
2039
-     * @throws InvalidArgumentException
2040
-     * @throws InvalidDataTypeException
2041
-     * @throws EE_Error
2042
-     * @throws InvalidInterfaceException
2043
-     */
2044
-    protected function _set_list_table_object()
2045
-    {
2046
-        if (isset($this->_route_config['list_table'])) {
2047
-            if (! class_exists($this->_route_config['list_table'])) {
2048
-                throw new EE_Error(
2049
-                    sprintf(
2050
-                        esc_html__(
2051
-                            '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.',
2052
-                            'event_espresso'
2053
-                        ),
2054
-                        $this->_route_config['list_table'],
2055
-                        $this->class_name
2056
-                    )
2057
-                );
2058
-            }
2059
-            $this->_list_table_object = $this->loader->getShared(
2060
-                $this->_route_config['list_table'],
2061
-                [
2062
-                    $this,
2063
-                    LoaderFactory::getShared(AdminListTableFilters::class),
2064
-                ]
2065
-            );
2066
-        }
2067
-    }
2068
-
2069
-
2070
-    /**
2071
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2072
-     *
2073
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2074
-     *                                                    urls.  The array should be indexed by the view it is being
2075
-     *                                                    added to.
2076
-     * @return array
2077
-     */
2078
-    public function get_list_table_view_RLs(array $extra_query_args = []): array
2079
-    {
2080
-        $extra_query_args = apply_filters(
2081
-            'FHEE__EE_Admin_Page__get_list_table_view_RLs__extra_query_args',
2082
-            $extra_query_args,
2083
-            $this
2084
-        );
2085
-        // cycle thru views
2086
-        foreach ($this->_views as $key => $view) {
2087
-            $query_args = [];
2088
-            // check for current view
2089
-            $this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2090
-            $query_args['action']          = $this->_req_action;
2091
-            $action_nonce                  = "{$this->_req_action}_nonce";
2092
-            $query_args[ $action_nonce ]   = wp_create_nonce($action_nonce);
2093
-            $query_args['status']          = $view['slug'];
2094
-            // merge any other arguments sent in.
2095
-            if (isset($extra_query_args[ $view['slug'] ])) {
2096
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2097
-            }
2098
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2099
-        }
2100
-        return $this->_views;
2101
-    }
2102
-
2103
-
2104
-    /**
2105
-     * generates a dropdown box for selecting the number of visible rows in an admin page list table
2106
-     *
2107
-     * @param int $max_entries total number of rows in the table
2108
-     * @return string
2109
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2110
-     *                         WP does it.
2111
-     */
2112
-    protected function _entries_per_page_dropdown(int $max_entries = 0): string
2113
-    {
2114
-        $values   = [10, 25, 50, 100];
2115
-        $per_page = $this->request->getRequestParam('per_page', 10, DataType::INT);
2116
-        if ($max_entries) {
2117
-            $values[] = $max_entries;
2118
-            sort($values);
2119
-        }
2120
-        $entries_per_page_dropdown = '
1815
+		$content .= $help_content;
1816
+		if ($display) {
1817
+			echo wp_kses($content, AllowedTags::getWithFormTags());
1818
+			return '';
1819
+		}
1820
+		return $content;
1821
+	}
1822
+
1823
+
1824
+	/**
1825
+	 * _add_global_screen_options
1826
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1827
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1828
+	 *
1829
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1830
+	 *         see also WP_Screen object documents...
1831
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1832
+	 * @abstract
1833
+	 * @return void
1834
+	 */
1835
+	private function _add_global_screen_options()
1836
+	{
1837
+	}
1838
+
1839
+
1840
+	/**
1841
+	 * _add_global_feature_pointers
1842
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1843
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1844
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1845
+	 *
1846
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (it's a final class so can't be
1847
+	 *         extended) also see:
1848
+	 * @link   http://eamann.com/tech/wordpress-portland/
1849
+	 * @abstract
1850
+	 * @return void
1851
+	 */
1852
+	private function _add_global_feature_pointers()
1853
+	{
1854
+	}
1855
+
1856
+
1857
+	/**
1858
+	 * load_global_scripts_styles
1859
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1860
+	 *
1861
+	 * @return void
1862
+	 */
1863
+	public function load_global_scripts_styles()
1864
+	{
1865
+		// add debugging styles
1866
+		if (WP_DEBUG) {
1867
+			add_action('admin_head', [$this, 'add_xdebug_style']);
1868
+		}
1869
+		// taking care of metaboxes
1870
+		if (
1871
+			empty($this->_cpt_route)
1872
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1873
+		) {
1874
+			wp_enqueue_script('dashboard');
1875
+		}
1876
+
1877
+		wp_enqueue_script(JqueryAssetManager::JS_HANDLE_JQUERY_UI_TOUCH_PUNCH);
1878
+		wp_enqueue_script(EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN);
1879
+		// LOCALIZED DATA
1880
+		// localize script for ajax lazy loading
1881
+		wp_localize_script(
1882
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1883
+			'eeLazyLoadingContainers',
1884
+			apply_filters(
1885
+				'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1886
+				['espresso_news_post_box_content']
1887
+			)
1888
+		);
1889
+		StatusChangeNotice::loadAssets();
1890
+
1891
+		add_filter(
1892
+			'admin_body_class',
1893
+			function ($classes) {
1894
+				if (strpos($classes, 'espresso-admin') === false) {
1895
+					$classes .= ' espresso-admin';
1896
+				}
1897
+				return $classes;
1898
+			}
1899
+		);
1900
+	}
1901
+
1902
+
1903
+	/**
1904
+	 *        admin_footer_scripts_eei18n_js_strings
1905
+	 *
1906
+	 * @return        void
1907
+	 */
1908
+	public function admin_footer_scripts_eei18n_js_strings()
1909
+	{
1910
+		EE_Registry::$i18n_js_strings['confirm_delete'] = wp_strip_all_tags(
1911
+			__(
1912
+				'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!!!',
1913
+				'event_espresso'
1914
+			)
1915
+		);
1916
+		// now add months and days of the week
1917
+		EE_Registry::$i18n_js_strings['January']   = wp_strip_all_tags(__('January', 'event_espresso'));
1918
+		EE_Registry::$i18n_js_strings['February']  = wp_strip_all_tags(__('February', 'event_espresso'));
1919
+		EE_Registry::$i18n_js_strings['March']     = wp_strip_all_tags(__('March', 'event_espresso'));
1920
+		EE_Registry::$i18n_js_strings['April']     = wp_strip_all_tags(__('April', 'event_espresso'));
1921
+		EE_Registry::$i18n_js_strings['May']       = wp_strip_all_tags(__('May', 'event_espresso'));
1922
+		EE_Registry::$i18n_js_strings['June']      = wp_strip_all_tags(__('June', 'event_espresso'));
1923
+		EE_Registry::$i18n_js_strings['July']      = wp_strip_all_tags(__('July', 'event_espresso'));
1924
+		EE_Registry::$i18n_js_strings['August']    = wp_strip_all_tags(__('August', 'event_espresso'));
1925
+		EE_Registry::$i18n_js_strings['September'] = wp_strip_all_tags(__('September', 'event_espresso'));
1926
+		EE_Registry::$i18n_js_strings['October']   = wp_strip_all_tags(__('October', 'event_espresso'));
1927
+		EE_Registry::$i18n_js_strings['November']  = wp_strip_all_tags(__('November', 'event_espresso'));
1928
+		EE_Registry::$i18n_js_strings['December']  = wp_strip_all_tags(__('December', 'event_espresso'));
1929
+		EE_Registry::$i18n_js_strings['Jan']       = wp_strip_all_tags(__('Jan', 'event_espresso'));
1930
+		EE_Registry::$i18n_js_strings['Feb']       = wp_strip_all_tags(__('Feb', 'event_espresso'));
1931
+		EE_Registry::$i18n_js_strings['Mar']       = wp_strip_all_tags(__('Mar', 'event_espresso'));
1932
+		EE_Registry::$i18n_js_strings['Apr']       = wp_strip_all_tags(__('Apr', 'event_espresso'));
1933
+		EE_Registry::$i18n_js_strings['May']       = wp_strip_all_tags(__('May', 'event_espresso'));
1934
+		EE_Registry::$i18n_js_strings['Jun']       = wp_strip_all_tags(__('Jun', 'event_espresso'));
1935
+		EE_Registry::$i18n_js_strings['Jul']       = wp_strip_all_tags(__('Jul', 'event_espresso'));
1936
+		EE_Registry::$i18n_js_strings['Aug']       = wp_strip_all_tags(__('Aug', 'event_espresso'));
1937
+		EE_Registry::$i18n_js_strings['Sep']       = wp_strip_all_tags(__('Sep', 'event_espresso'));
1938
+		EE_Registry::$i18n_js_strings['Oct']       = wp_strip_all_tags(__('Oct', 'event_espresso'));
1939
+		EE_Registry::$i18n_js_strings['Nov']       = wp_strip_all_tags(__('Nov', 'event_espresso'));
1940
+		EE_Registry::$i18n_js_strings['Dec']       = wp_strip_all_tags(__('Dec', 'event_espresso'));
1941
+		EE_Registry::$i18n_js_strings['Sunday']    = wp_strip_all_tags(__('Sunday', 'event_espresso'));
1942
+		EE_Registry::$i18n_js_strings['Monday']    = wp_strip_all_tags(__('Monday', 'event_espresso'));
1943
+		EE_Registry::$i18n_js_strings['Tuesday']   = wp_strip_all_tags(__('Tuesday', 'event_espresso'));
1944
+		EE_Registry::$i18n_js_strings['Wednesday'] = wp_strip_all_tags(__('Wednesday', 'event_espresso'));
1945
+		EE_Registry::$i18n_js_strings['Thursday']  = wp_strip_all_tags(__('Thursday', 'event_espresso'));
1946
+		EE_Registry::$i18n_js_strings['Friday']    = wp_strip_all_tags(__('Friday', 'event_espresso'));
1947
+		EE_Registry::$i18n_js_strings['Saturday']  = wp_strip_all_tags(__('Saturday', 'event_espresso'));
1948
+		EE_Registry::$i18n_js_strings['Sun']       = wp_strip_all_tags(__('Sun', 'event_espresso'));
1949
+		EE_Registry::$i18n_js_strings['Mon']       = wp_strip_all_tags(__('Mon', 'event_espresso'));
1950
+		EE_Registry::$i18n_js_strings['Tue']       = wp_strip_all_tags(__('Tue', 'event_espresso'));
1951
+		EE_Registry::$i18n_js_strings['Wed']       = wp_strip_all_tags(__('Wed', 'event_espresso'));
1952
+		EE_Registry::$i18n_js_strings['Thu']       = wp_strip_all_tags(__('Thu', 'event_espresso'));
1953
+		EE_Registry::$i18n_js_strings['Fri']       = wp_strip_all_tags(__('Fri', 'event_espresso'));
1954
+		EE_Registry::$i18n_js_strings['Sat']       = wp_strip_all_tags(__('Sat', 'event_espresso'));
1955
+	}
1956
+
1957
+
1958
+	/**
1959
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1960
+	 *
1961
+	 * @return        void
1962
+	 */
1963
+	public function add_xdebug_style()
1964
+	{
1965
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
1966
+	}
1967
+
1968
+
1969
+	/************************/
1970
+	/** LIST TABLE METHODS **/
1971
+	/************************/
1972
+	/**
1973
+	 * this sets up the list table if the current view requires it.
1974
+	 *
1975
+	 * @return void
1976
+	 * @throws EE_Error
1977
+	 * @throws InvalidArgumentException
1978
+	 * @throws InvalidDataTypeException
1979
+	 * @throws InvalidInterfaceException
1980
+	 */
1981
+	protected function _set_list_table()
1982
+	{
1983
+		// first is this a list_table view?
1984
+		if (! isset($this->_route_config['list_table'])) {
1985
+			return;
1986
+		} //not a list_table view so get out.
1987
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
1988
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
1989
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1990
+			// user error msg
1991
+			$error_msg = esc_html__(
1992
+				'An error occurred. The requested list table views could not be found.',
1993
+				'event_espresso'
1994
+			);
1995
+			// developer error msg
1996
+			$error_msg .= '||'
1997
+						  . sprintf(
1998
+							  esc_html__(
1999
+								  '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.',
2000
+								  'event_espresso'
2001
+							  ),
2002
+							  $this->_req_action,
2003
+							  $list_table_view
2004
+						  );
2005
+			throw new EE_Error($error_msg);
2006
+		}
2007
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2008
+		$this->_views = apply_filters(
2009
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2010
+			$this->_views
2011
+		);
2012
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2013
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2014
+		$this->_set_list_table_view();
2015
+		$this->_set_list_table_object();
2016
+	}
2017
+
2018
+
2019
+	/**
2020
+	 * set current view for List Table
2021
+	 *
2022
+	 * @return void
2023
+	 */
2024
+	protected function _set_list_table_view()
2025
+	{
2026
+		$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2027
+		$status      = $this->request->getRequestParam('status', null, DataType::KEY);
2028
+		$this->_view = $status && array_key_exists($status, $this->_views)
2029
+			? $status
2030
+			: $this->_view;
2031
+	}
2032
+
2033
+
2034
+	/**
2035
+	 * _set_list_table_object
2036
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2037
+	 *
2038
+	 * @throws InvalidInterfaceException
2039
+	 * @throws InvalidArgumentException
2040
+	 * @throws InvalidDataTypeException
2041
+	 * @throws EE_Error
2042
+	 * @throws InvalidInterfaceException
2043
+	 */
2044
+	protected function _set_list_table_object()
2045
+	{
2046
+		if (isset($this->_route_config['list_table'])) {
2047
+			if (! class_exists($this->_route_config['list_table'])) {
2048
+				throw new EE_Error(
2049
+					sprintf(
2050
+						esc_html__(
2051
+							'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.',
2052
+							'event_espresso'
2053
+						),
2054
+						$this->_route_config['list_table'],
2055
+						$this->class_name
2056
+					)
2057
+				);
2058
+			}
2059
+			$this->_list_table_object = $this->loader->getShared(
2060
+				$this->_route_config['list_table'],
2061
+				[
2062
+					$this,
2063
+					LoaderFactory::getShared(AdminListTableFilters::class),
2064
+				]
2065
+			);
2066
+		}
2067
+	}
2068
+
2069
+
2070
+	/**
2071
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2072
+	 *
2073
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2074
+	 *                                                    urls.  The array should be indexed by the view it is being
2075
+	 *                                                    added to.
2076
+	 * @return array
2077
+	 */
2078
+	public function get_list_table_view_RLs(array $extra_query_args = []): array
2079
+	{
2080
+		$extra_query_args = apply_filters(
2081
+			'FHEE__EE_Admin_Page__get_list_table_view_RLs__extra_query_args',
2082
+			$extra_query_args,
2083
+			$this
2084
+		);
2085
+		// cycle thru views
2086
+		foreach ($this->_views as $key => $view) {
2087
+			$query_args = [];
2088
+			// check for current view
2089
+			$this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2090
+			$query_args['action']          = $this->_req_action;
2091
+			$action_nonce                  = "{$this->_req_action}_nonce";
2092
+			$query_args[ $action_nonce ]   = wp_create_nonce($action_nonce);
2093
+			$query_args['status']          = $view['slug'];
2094
+			// merge any other arguments sent in.
2095
+			if (isset($extra_query_args[ $view['slug'] ])) {
2096
+				$query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2097
+			}
2098
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2099
+		}
2100
+		return $this->_views;
2101
+	}
2102
+
2103
+
2104
+	/**
2105
+	 * generates a dropdown box for selecting the number of visible rows in an admin page list table
2106
+	 *
2107
+	 * @param int $max_entries total number of rows in the table
2108
+	 * @return string
2109
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2110
+	 *                         WP does it.
2111
+	 */
2112
+	protected function _entries_per_page_dropdown(int $max_entries = 0): string
2113
+	{
2114
+		$values   = [10, 25, 50, 100];
2115
+		$per_page = $this->request->getRequestParam('per_page', 10, DataType::INT);
2116
+		if ($max_entries) {
2117
+			$values[] = $max_entries;
2118
+			sort($values);
2119
+		}
2120
+		$entries_per_page_dropdown = '
2121 2121
 			<div id="entries-per-page-dv" class="alignleft actions">
2122 2122
 				<label class="hide-if-no-js">
2123 2123
 					Show
2124 2124
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2125
-        foreach ($values as $value) {
2126
-            if ($value < $max_entries) {
2127
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2128
-                $entries_per_page_dropdown .= '
2125
+		foreach ($values as $value) {
2126
+			if ($value < $max_entries) {
2127
+				$selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2128
+				$entries_per_page_dropdown .= '
2129 2129
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2130
-            }
2131
-        }
2132
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2133
-        $entries_per_page_dropdown .= '
2130
+			}
2131
+		}
2132
+		$selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2133
+		$entries_per_page_dropdown .= '
2134 2134
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2135
-        $entries_per_page_dropdown .= '
2135
+		$entries_per_page_dropdown .= '
2136 2136
 					</select>
2137 2137
 					entries
2138 2138
 				</label>
2139 2139
 				<input id="entries-per-page-btn" class="button button--secondary" type="submit" value="Go" >
2140 2140
 			</div>
2141 2141
 		';
2142
-        return $entries_per_page_dropdown;
2143
-    }
2144
-
2145
-
2146
-    /**
2147
-     *        _set_search_attributes
2148
-     *
2149
-     * @return        void
2150
-     */
2151
-    public function _set_search_attributes()
2152
-    {
2153
-        $this->_template_args['search']['btn_label'] = sprintf(
2154
-            esc_html__('Search %s', 'event_espresso'),
2155
-            empty($this->_search_btn_label) ? $this->page_label
2156
-                : $this->_search_btn_label
2157
-        );
2158
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2159
-    }
2160
-
2161
-
2162
-
2163
-    /*** END LIST TABLE METHODS **/
2164
-
2165
-    /**
2166
-     * @return void
2167
-     * @throws EE_Error
2168
-     */
2169
-    public function addRegisteredMetaBoxes()
2170
-    {
2171
-        remove_action('add_meta_boxes', [$this, 'addRegisteredMetaBoxes'], 99);
2172
-        $this->_add_registered_meta_boxes();
2173
-    }
2174
-
2175
-
2176
-    /**
2177
-     * _add_registered_metaboxes
2178
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2179
-     *
2180
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2181
-     * @return void
2182
-     * @throws EE_Error
2183
-     */
2184
-    private function _add_registered_meta_boxes()
2185
-    {
2186
-        // we only add meta boxes if the page_route calls for it
2187
-        if (isset($this->_route_config['metaboxes']) && is_array($this->_route_config['metaboxes'])) {
2188
-            // this simply loops through the callbacks provided
2189
-            // and checks if there is a corresponding callback registered by the child
2190
-            // if there is then we go ahead and process the metabox loader.
2191
-            foreach ($this->_route_config['metaboxes'] as $key => $metabox_callback) {
2192
-                // first check for Closures
2193
-                if ($metabox_callback instanceof Closure) {
2194
-                    $result = $metabox_callback();
2195
-                } elseif (is_callable($metabox_callback)) {
2196
-                    $result = call_user_func($metabox_callback);
2197
-                } elseif (method_exists($this, $metabox_callback)) {
2198
-                    $result = $this->{$metabox_callback}();
2199
-                } else {
2200
-                    $result = false;
2201
-                }
2202
-                if ($result === false) {
2203
-                    // user error msg
2204
-                    $error_msg = esc_html__(
2205
-                        'An error occurred. The  requested metabox could not be found.',
2206
-                        'event_espresso'
2207
-                    );
2208
-                    // developer error msg
2209
-                    $error_msg .= '||'
2210
-                                  . sprintf(
2211
-                                      esc_html__(
2212
-                                          '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.',
2213
-                                          'event_espresso'
2214
-                                      ),
2215
-                                      $metabox_callback
2216
-                                  );
2217
-                    throw new EE_Error($error_msg);
2218
-                }
2219
-                unset($this->_route_config['metaboxes'][ $key ]);
2220
-            }
2221
-        }
2222
-    }
2223
-
2224
-
2225
-    /**
2226
-     * _add_screen_columns
2227
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2228
-     * the dynamic column template and we'll set up the column options for the page.
2229
-     *
2230
-     * @return void
2231
-     */
2232
-    private function _add_screen_columns()
2233
-    {
2234
-        if (
2235
-            isset($this->_route_config['columns'])
2236
-            && is_array($this->_route_config['columns'])
2237
-            && count($this->_route_config['columns']) === 2
2238
-        ) {
2239
-            add_screen_option(
2240
-                'layout_columns',
2241
-                [
2242
-                    'max'     => (int) $this->_route_config['columns'][0],
2243
-                    'default' => (int) $this->_route_config['columns'][1],
2244
-                ]
2245
-            );
2246
-            $this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2247
-            $screen_id                                           = $this->_current_screen->id;
2248
-            $screen_columns                                      = (int) get_user_option("screen_layout_$screen_id");
2249
-            $total_columns                                       = ! empty($screen_columns)
2250
-                ? $screen_columns
2251
-                : $this->_route_config['columns'][1];
2252
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2253
-            $this->_template_args['current_page']                = $this->_wp_page_slug;
2254
-            $this->_template_args['screen']                      = $this->_current_screen;
2255
-            $this->_column_template_path                         = EE_ADMIN_TEMPLATE
2256
-                                                                   . 'admin_details_metabox_column_wrapper.template.php';
2257
-            // finally if we don't have has_metaboxes set in the route config
2258
-            // let's make sure it IS set otherwise the necessary hidden fields for this won't be loaded.
2259
-            $this->_route_config['has_metaboxes'] = true;
2260
-        }
2261
-    }
2262
-
2263
-
2264
-
2265
-    /** GLOBALLY AVAILABLE METABOXES **/
2266
-
2267
-
2268
-    /**
2269
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2270
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2271
-     * these get loaded on.
2272
-     */
2273
-    private function _espresso_news_post_box()
2274
-    {
2275
-        $news_box_title = apply_filters(
2276
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2277
-            esc_html__('New @ Event Espresso', 'event_espresso')
2278
-        );
2279
-        $this->addMetaBox(
2280
-            'espresso_news_post_box',
2281
-            $news_box_title,
2282
-            [
2283
-                $this,
2284
-                'espresso_news_post_box',
2285
-            ],
2286
-            $this->_wp_page_slug,
2287
-            'side',
2288
-            'low'
2289
-        );
2290
-    }
2291
-
2292
-
2293
-    /**
2294
-     * Code for setting up espresso ratings request metabox.
2295
-     */
2296
-    protected function _espresso_ratings_request()
2297
-    {
2298
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2299
-            return;
2300
-        }
2301
-        $ratings_box_title = apply_filters(
2302
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2303
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2304
-        );
2305
-        $this->addMetaBox(
2306
-            'espresso_ratings_request',
2307
-            $ratings_box_title,
2308
-            [
2309
-                $this,
2310
-                'espresso_ratings_request',
2311
-            ],
2312
-            $this->_wp_page_slug,
2313
-            'side'
2314
-        );
2315
-    }
2316
-
2317
-
2318
-    /**
2319
-     * Code for setting up espresso ratings request metabox content.
2320
-     *
2321
-     * @throws DomainException
2322
-     */
2323
-    public function espresso_ratings_request()
2324
-    {
2325
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2326
-    }
2327
-
2328
-
2329
-    public static function cached_rss_display(string $rss_id, string $url): bool
2330
-    {
2331
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2332
-                     . esc_html__('Loading&#8230;', 'event_espresso')
2333
-                     . '</p><p class="hide-if-js">'
2334
-                     . esc_html__('This widget requires JavaScript.', 'event_espresso')
2335
-                     . '</p>';
2336
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2337
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2338
-        $post      = '</div>' . "\n";
2339
-        $cache_key = 'ee_rss_' . md5($rss_id);
2340
-        $output    = get_transient($cache_key);
2341
-        if ($output !== false) {
2342
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2343
-            return true;
2344
-        }
2345
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2346
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2347
-            return false;
2348
-        }
2349
-        ob_start();
2350
-        wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2351
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2352
-        return true;
2353
-    }
2354
-
2355
-
2356
-    public function espresso_news_post_box()
2357
-    {
2358
-        ?>
2142
+		return $entries_per_page_dropdown;
2143
+	}
2144
+
2145
+
2146
+	/**
2147
+	 *        _set_search_attributes
2148
+	 *
2149
+	 * @return        void
2150
+	 */
2151
+	public function _set_search_attributes()
2152
+	{
2153
+		$this->_template_args['search']['btn_label'] = sprintf(
2154
+			esc_html__('Search %s', 'event_espresso'),
2155
+			empty($this->_search_btn_label) ? $this->page_label
2156
+				: $this->_search_btn_label
2157
+		);
2158
+		$this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2159
+	}
2160
+
2161
+
2162
+
2163
+	/*** END LIST TABLE METHODS **/
2164
+
2165
+	/**
2166
+	 * @return void
2167
+	 * @throws EE_Error
2168
+	 */
2169
+	public function addRegisteredMetaBoxes()
2170
+	{
2171
+		remove_action('add_meta_boxes', [$this, 'addRegisteredMetaBoxes'], 99);
2172
+		$this->_add_registered_meta_boxes();
2173
+	}
2174
+
2175
+
2176
+	/**
2177
+	 * _add_registered_metaboxes
2178
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2179
+	 *
2180
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2181
+	 * @return void
2182
+	 * @throws EE_Error
2183
+	 */
2184
+	private function _add_registered_meta_boxes()
2185
+	{
2186
+		// we only add meta boxes if the page_route calls for it
2187
+		if (isset($this->_route_config['metaboxes']) && is_array($this->_route_config['metaboxes'])) {
2188
+			// this simply loops through the callbacks provided
2189
+			// and checks if there is a corresponding callback registered by the child
2190
+			// if there is then we go ahead and process the metabox loader.
2191
+			foreach ($this->_route_config['metaboxes'] as $key => $metabox_callback) {
2192
+				// first check for Closures
2193
+				if ($metabox_callback instanceof Closure) {
2194
+					$result = $metabox_callback();
2195
+				} elseif (is_callable($metabox_callback)) {
2196
+					$result = call_user_func($metabox_callback);
2197
+				} elseif (method_exists($this, $metabox_callback)) {
2198
+					$result = $this->{$metabox_callback}();
2199
+				} else {
2200
+					$result = false;
2201
+				}
2202
+				if ($result === false) {
2203
+					// user error msg
2204
+					$error_msg = esc_html__(
2205
+						'An error occurred. The  requested metabox could not be found.',
2206
+						'event_espresso'
2207
+					);
2208
+					// developer error msg
2209
+					$error_msg .= '||'
2210
+								  . sprintf(
2211
+									  esc_html__(
2212
+										  '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.',
2213
+										  'event_espresso'
2214
+									  ),
2215
+									  $metabox_callback
2216
+								  );
2217
+					throw new EE_Error($error_msg);
2218
+				}
2219
+				unset($this->_route_config['metaboxes'][ $key ]);
2220
+			}
2221
+		}
2222
+	}
2223
+
2224
+
2225
+	/**
2226
+	 * _add_screen_columns
2227
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2228
+	 * the dynamic column template and we'll set up the column options for the page.
2229
+	 *
2230
+	 * @return void
2231
+	 */
2232
+	private function _add_screen_columns()
2233
+	{
2234
+		if (
2235
+			isset($this->_route_config['columns'])
2236
+			&& is_array($this->_route_config['columns'])
2237
+			&& count($this->_route_config['columns']) === 2
2238
+		) {
2239
+			add_screen_option(
2240
+				'layout_columns',
2241
+				[
2242
+					'max'     => (int) $this->_route_config['columns'][0],
2243
+					'default' => (int) $this->_route_config['columns'][1],
2244
+				]
2245
+			);
2246
+			$this->_template_args['num_columns']                 = $this->_route_config['columns'][0];
2247
+			$screen_id                                           = $this->_current_screen->id;
2248
+			$screen_columns                                      = (int) get_user_option("screen_layout_$screen_id");
2249
+			$total_columns                                       = ! empty($screen_columns)
2250
+				? $screen_columns
2251
+				: $this->_route_config['columns'][1];
2252
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2253
+			$this->_template_args['current_page']                = $this->_wp_page_slug;
2254
+			$this->_template_args['screen']                      = $this->_current_screen;
2255
+			$this->_column_template_path                         = EE_ADMIN_TEMPLATE
2256
+																   . 'admin_details_metabox_column_wrapper.template.php';
2257
+			// finally if we don't have has_metaboxes set in the route config
2258
+			// let's make sure it IS set otherwise the necessary hidden fields for this won't be loaded.
2259
+			$this->_route_config['has_metaboxes'] = true;
2260
+		}
2261
+	}
2262
+
2263
+
2264
+
2265
+	/** GLOBALLY AVAILABLE METABOXES **/
2266
+
2267
+
2268
+	/**
2269
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2270
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2271
+	 * these get loaded on.
2272
+	 */
2273
+	private function _espresso_news_post_box()
2274
+	{
2275
+		$news_box_title = apply_filters(
2276
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2277
+			esc_html__('New @ Event Espresso', 'event_espresso')
2278
+		);
2279
+		$this->addMetaBox(
2280
+			'espresso_news_post_box',
2281
+			$news_box_title,
2282
+			[
2283
+				$this,
2284
+				'espresso_news_post_box',
2285
+			],
2286
+			$this->_wp_page_slug,
2287
+			'side',
2288
+			'low'
2289
+		);
2290
+	}
2291
+
2292
+
2293
+	/**
2294
+	 * Code for setting up espresso ratings request metabox.
2295
+	 */
2296
+	protected function _espresso_ratings_request()
2297
+	{
2298
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2299
+			return;
2300
+		}
2301
+		$ratings_box_title = apply_filters(
2302
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2303
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2304
+		);
2305
+		$this->addMetaBox(
2306
+			'espresso_ratings_request',
2307
+			$ratings_box_title,
2308
+			[
2309
+				$this,
2310
+				'espresso_ratings_request',
2311
+			],
2312
+			$this->_wp_page_slug,
2313
+			'side'
2314
+		);
2315
+	}
2316
+
2317
+
2318
+	/**
2319
+	 * Code for setting up espresso ratings request metabox content.
2320
+	 *
2321
+	 * @throws DomainException
2322
+	 */
2323
+	public function espresso_ratings_request()
2324
+	{
2325
+		EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2326
+	}
2327
+
2328
+
2329
+	public static function cached_rss_display(string $rss_id, string $url): bool
2330
+	{
2331
+		$loading   = '<p class="widget-loading hide-if-no-js">'
2332
+					 . esc_html__('Loading&#8230;', 'event_espresso')
2333
+					 . '</p><p class="hide-if-js">'
2334
+					 . esc_html__('This widget requires JavaScript.', 'event_espresso')
2335
+					 . '</p>';
2336
+		$pre       = '<div class="espresso-rss-display">' . "\n\t";
2337
+		$pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2338
+		$post      = '</div>' . "\n";
2339
+		$cache_key = 'ee_rss_' . md5($rss_id);
2340
+		$output    = get_transient($cache_key);
2341
+		if ($output !== false) {
2342
+			echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2343
+			return true;
2344
+		}
2345
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2346
+			echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2347
+			return false;
2348
+		}
2349
+		ob_start();
2350
+		wp_widget_rss_output($url, ['show_date' => 0, 'items' => 5]);
2351
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2352
+		return true;
2353
+	}
2354
+
2355
+
2356
+	public function espresso_news_post_box()
2357
+	{
2358
+		?>
2359 2359
 <div class="padding">
2360 2360
     <div id="espresso_news_post_box_content" class="infolinks">
2361 2361
         <?php
2362
-                // Get RSS Feed(s)
2363
-                EE_Admin_Page::cached_rss_display(
2364
-                    'espresso_news_post_box_content',
2365
-                    esc_url_raw(
2366
-                        apply_filters(
2367
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2368
-                            'https://eventespresso.com/feed/'
2369
-                        )
2370
-                    )
2371
-                );
2372
-        ?>
2362
+				// Get RSS Feed(s)
2363
+				EE_Admin_Page::cached_rss_display(
2364
+					'espresso_news_post_box_content',
2365
+					esc_url_raw(
2366
+						apply_filters(
2367
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2368
+							'https://eventespresso.com/feed/'
2369
+						)
2370
+					)
2371
+				);
2372
+		?>
2373 2373
     </div>
2374 2374
     <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2375 2375
 </div>
2376 2376
 <?php
2377
-    }
2378
-
2379
-
2380
-    private function _espresso_links_post_box()
2381
-    {
2382
-        // Hiding until we actually have content to put in here...
2383
-        // $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2384
-    }
2385
-
2386
-
2387
-    public function espresso_links_post_box()
2388
-    {
2389
-        // Hiding until we actually have content to put in here...
2390
-        // EEH_Template::display_template(
2391
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2392
-        // );
2393
-    }
2394
-
2395
-
2396
-    protected function _espresso_sponsors_post_box()
2397
-    {
2398
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2399
-            $this->addMetaBox(
2400
-                'espresso_sponsors_post_box',
2401
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2402
-                [$this, 'espresso_sponsors_post_box'],
2403
-                $this->_wp_page_slug,
2404
-                'side'
2405
-            );
2406
-        }
2407
-    }
2408
-
2409
-
2410
-    public function espresso_sponsors_post_box()
2411
-    {
2412
-        EEH_Template::display_template(
2413
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2414
-        );
2415
-    }
2416
-
2417
-
2418
-    /**
2419
-     * if there is [ 'label' => [ 'publishbox' => 'some title' ]]
2420
-     * present in the _page_config array, then we'll use that for the metabox label.
2421
-     * Otherwise we'll just use publish
2422
-     * (publishbox itself could be an array of labels indexed by routes)
2423
-     *
2424
-     * @return string
2425
-     * @since   5.0.0.p
2426
-     */
2427
-    protected function getPublishBoxTitle(): string
2428
-    {
2429
-        $publish_box_title = esc_html__('Publish', 'event_espresso');
2430
-        if (! empty($this->_labels['publishbox'])) {
2431
-            if (is_array($this->_labels['publishbox'])) {
2432
-                $publish_box_title = $this->_labels['publishbox'][ $this->_req_action ] ?? $publish_box_title;
2433
-            } else {
2434
-                $publish_box_title = $this->_labels['publishbox'];
2435
-            }
2436
-        }
2437
-        return apply_filters(
2438
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2439
-            $publish_box_title,
2440
-            $this->_req_action,
2441
-            $this
2442
-        );
2443
-    }
2444
-
2445
-
2446
-    /**
2447
-     * @throws EE_Error
2448
-     */
2449
-    private function _publish_post_box()
2450
-    {
2451
-        $title = $this->getPublishBoxTitle();
2452
-        if (empty($this->_template_args['save_buttons'])) {
2453
-            $this->_set_publish_post_box_vars(sanitize_key($title), "espresso_{$this->page_slug}_editor_overview");
2454
-        } else {
2455
-            $this->addPublishPostMetaBoxHiddenFields(
2456
-                sanitize_key($title),
2457
-                ['type' => 'hidden', 'value' => "espresso_{$this->page_slug}_editor_overview"]
2458
-            );
2459
-        }
2460
-        $this->addMetaBox(
2461
-            "espresso_{$this->page_slug}_editor_overview",
2462
-            $title,
2463
-            [$this, 'editor_overview'],
2464
-            $this->_current_screen->id,
2465
-            'side',
2466
-            'high'
2467
-        );
2468
-    }
2469
-
2470
-
2471
-    public function editor_overview()
2472
-    {
2473
-        /**
2474
-         * @var string $publish_box_extra_content
2475
-         * @var string $publish_hidden_fields
2476
-         * @var string $publish_delete_link
2477
-         * @var string $save_buttons
2478
-         */
2479
-        // if we have extra content set let's add it in if not make sure its empty
2480
-        $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2481
-        echo EEH_Template::display_template(
2482
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2483
-            $this->_template_args,
2484
-            true
2485
-        );
2486
-    }
2487
-
2488
-
2489
-    /** end of globally available metaboxes section **/
2490
-
2491
-
2492
-    /**
2493
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2494
-     * Note: currently there is no validation for this.  However, if you want the delete button, the
2495
-     * save, and save and close buttons to work properly, then you will want to include a
2496
-     * values for the name and id arguments.
2497
-     *
2498
-     * @param string|null $name                     key used for the action ID (i.e. event_id)
2499
-     * @param int|string  $id                       id attached to the item published
2500
-     * @param string|null $delete                   page route callback for the delete action
2501
-     * @param string|null $save_close_redirect_URL  custom URL to redirect to after Save & Close has been completed
2502
-     * @param bool        $both_btns                whether to display BOTH the "Save & Close" and "Save" buttons
2503
-     *                                              or just the "Save" button
2504
-     * @throws EE_Error
2505
-     * @throws InvalidArgumentException
2506
-     * @throws InvalidDataTypeException
2507
-     * @throws InvalidInterfaceException
2508
-     * @todo  Add in validation for name/id arguments.
2509
-     */
2510
-    protected function _set_publish_post_box_vars(
2511
-        ?string $name = '',
2512
-        $id = 0,
2513
-        ?string $delete = '',
2514
-        ?string $save_close_redirect_URL = '',
2515
-        bool $both_btns = true
2516
-    ) {
2517
-        // if Save & Close, use a custom redirect URL or default to the main page?
2518
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2519
-            ? $save_close_redirect_URL
2520
-            : $this->_admin_base_url;
2521
-        // create the Save & Close and Save buttons
2522
-        $this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2523
-        // if we have extra content set let's add it in if not make sure its empty
2524
-        $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2525
-        if ($delete && ! empty($id) && empty($this->_template_args['publish_delete_link'])) {
2526
-            // make sure we have a default if just true is sent.
2527
-            $delete                                      = ! empty($delete) ? $delete : 'delete';
2528
-            $this->_template_args['publish_delete_link'] = $this->get_action_link_or_button(
2529
-                $delete,
2530
-                $delete,
2531
-                [$name => $id],
2532
-                'submitdelete deletion button button--outline button--caution'
2533
-            );
2534
-        }
2535
-        if (! isset($this->_template_args['publish_delete_link'])) {
2536
-            $this->_template_args['publish_delete_link'] = '';
2537
-        }
2538
-        if (! empty($name) && ! empty($id)) {
2539
-            $this->addPublishPostMetaBoxHiddenFields($name, ['type' => 'hidden', 'value' => $id]);
2540
-        }
2541
-        $hidden_fields = $this->_generate_admin_form_fields($this->publish_post_meta_box_hidden_fields, 'array');
2542
-        // add hidden fields
2543
-        $this->_template_args['publish_hidden_fields'] = $this->_template_args['publish_hidden_fields'] ?? '';
2544
-        foreach ($hidden_fields as $hidden_field) {
2545
-            $this->_template_args['publish_hidden_fields'] .= $hidden_field['field'] ?? '';
2546
-        }
2547
-    }
2548
-
2549
-
2550
-    /**
2551
-     * @param string|null $name
2552
-     * @param int|string  $id
2553
-     * @param string|null $delete
2554
-     * @param string|null $save_close_redirect_URL
2555
-     * @param bool        $both_btns
2556
-     * @throws EE_Error
2557
-     */
2558
-    public function set_publish_post_box_vars(
2559
-        ?string $name = '',
2560
-        $id = 0,
2561
-        ?string $delete = '',
2562
-        ?string $save_close_redirect_URL = '',
2563
-        bool $both_btns = false
2564
-    ) {
2565
-        $this->_set_publish_post_box_vars($name, $id, $delete, $save_close_redirect_URL, $both_btns);
2566
-    }
2567
-
2568
-
2569
-    protected function addPublishPostMetaBoxHiddenFields(string $field_name, array $field_attributes)
2570
-    {
2571
-        $this->publish_post_meta_box_hidden_fields[ $field_name ] = $field_attributes;
2572
-    }
2573
-
2574
-
2575
-    /**
2576
-     * displays an error message to ppl who have javascript disabled
2577
-     *
2578
-     * @return void
2579
-     */
2580
-    private function _display_no_javascript_warning()
2581
-    {
2582
-        ?>
2377
+	}
2378
+
2379
+
2380
+	private function _espresso_links_post_box()
2381
+	{
2382
+		// Hiding until we actually have content to put in here...
2383
+		// $this->addMetaBox('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2384
+	}
2385
+
2386
+
2387
+	public function espresso_links_post_box()
2388
+	{
2389
+		// Hiding until we actually have content to put in here...
2390
+		// EEH_Template::display_template(
2391
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2392
+		// );
2393
+	}
2394
+
2395
+
2396
+	protected function _espresso_sponsors_post_box()
2397
+	{
2398
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2399
+			$this->addMetaBox(
2400
+				'espresso_sponsors_post_box',
2401
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2402
+				[$this, 'espresso_sponsors_post_box'],
2403
+				$this->_wp_page_slug,
2404
+				'side'
2405
+			);
2406
+		}
2407
+	}
2408
+
2409
+
2410
+	public function espresso_sponsors_post_box()
2411
+	{
2412
+		EEH_Template::display_template(
2413
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2414
+		);
2415
+	}
2416
+
2417
+
2418
+	/**
2419
+	 * if there is [ 'label' => [ 'publishbox' => 'some title' ]]
2420
+	 * present in the _page_config array, then we'll use that for the metabox label.
2421
+	 * Otherwise we'll just use publish
2422
+	 * (publishbox itself could be an array of labels indexed by routes)
2423
+	 *
2424
+	 * @return string
2425
+	 * @since   5.0.0.p
2426
+	 */
2427
+	protected function getPublishBoxTitle(): string
2428
+	{
2429
+		$publish_box_title = esc_html__('Publish', 'event_espresso');
2430
+		if (! empty($this->_labels['publishbox'])) {
2431
+			if (is_array($this->_labels['publishbox'])) {
2432
+				$publish_box_title = $this->_labels['publishbox'][ $this->_req_action ] ?? $publish_box_title;
2433
+			} else {
2434
+				$publish_box_title = $this->_labels['publishbox'];
2435
+			}
2436
+		}
2437
+		return apply_filters(
2438
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2439
+			$publish_box_title,
2440
+			$this->_req_action,
2441
+			$this
2442
+		);
2443
+	}
2444
+
2445
+
2446
+	/**
2447
+	 * @throws EE_Error
2448
+	 */
2449
+	private function _publish_post_box()
2450
+	{
2451
+		$title = $this->getPublishBoxTitle();
2452
+		if (empty($this->_template_args['save_buttons'])) {
2453
+			$this->_set_publish_post_box_vars(sanitize_key($title), "espresso_{$this->page_slug}_editor_overview");
2454
+		} else {
2455
+			$this->addPublishPostMetaBoxHiddenFields(
2456
+				sanitize_key($title),
2457
+				['type' => 'hidden', 'value' => "espresso_{$this->page_slug}_editor_overview"]
2458
+			);
2459
+		}
2460
+		$this->addMetaBox(
2461
+			"espresso_{$this->page_slug}_editor_overview",
2462
+			$title,
2463
+			[$this, 'editor_overview'],
2464
+			$this->_current_screen->id,
2465
+			'side',
2466
+			'high'
2467
+		);
2468
+	}
2469
+
2470
+
2471
+	public function editor_overview()
2472
+	{
2473
+		/**
2474
+		 * @var string $publish_box_extra_content
2475
+		 * @var string $publish_hidden_fields
2476
+		 * @var string $publish_delete_link
2477
+		 * @var string $save_buttons
2478
+		 */
2479
+		// if we have extra content set let's add it in if not make sure its empty
2480
+		$this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2481
+		echo EEH_Template::display_template(
2482
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2483
+			$this->_template_args,
2484
+			true
2485
+		);
2486
+	}
2487
+
2488
+
2489
+	/** end of globally available metaboxes section **/
2490
+
2491
+
2492
+	/**
2493
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2494
+	 * Note: currently there is no validation for this.  However, if you want the delete button, the
2495
+	 * save, and save and close buttons to work properly, then you will want to include a
2496
+	 * values for the name and id arguments.
2497
+	 *
2498
+	 * @param string|null $name                     key used for the action ID (i.e. event_id)
2499
+	 * @param int|string  $id                       id attached to the item published
2500
+	 * @param string|null $delete                   page route callback for the delete action
2501
+	 * @param string|null $save_close_redirect_URL  custom URL to redirect to after Save & Close has been completed
2502
+	 * @param bool        $both_btns                whether to display BOTH the "Save & Close" and "Save" buttons
2503
+	 *                                              or just the "Save" button
2504
+	 * @throws EE_Error
2505
+	 * @throws InvalidArgumentException
2506
+	 * @throws InvalidDataTypeException
2507
+	 * @throws InvalidInterfaceException
2508
+	 * @todo  Add in validation for name/id arguments.
2509
+	 */
2510
+	protected function _set_publish_post_box_vars(
2511
+		?string $name = '',
2512
+		$id = 0,
2513
+		?string $delete = '',
2514
+		?string $save_close_redirect_URL = '',
2515
+		bool $both_btns = true
2516
+	) {
2517
+		// if Save & Close, use a custom redirect URL or default to the main page?
2518
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2519
+			? $save_close_redirect_URL
2520
+			: $this->_admin_base_url;
2521
+		// create the Save & Close and Save buttons
2522
+		$this->_set_save_buttons($both_btns, [], [], $save_close_redirect_URL);
2523
+		// if we have extra content set let's add it in if not make sure its empty
2524
+		$this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2525
+		if ($delete && ! empty($id) && empty($this->_template_args['publish_delete_link'])) {
2526
+			// make sure we have a default if just true is sent.
2527
+			$delete                                      = ! empty($delete) ? $delete : 'delete';
2528
+			$this->_template_args['publish_delete_link'] = $this->get_action_link_or_button(
2529
+				$delete,
2530
+				$delete,
2531
+				[$name => $id],
2532
+				'submitdelete deletion button button--outline button--caution'
2533
+			);
2534
+		}
2535
+		if (! isset($this->_template_args['publish_delete_link'])) {
2536
+			$this->_template_args['publish_delete_link'] = '';
2537
+		}
2538
+		if (! empty($name) && ! empty($id)) {
2539
+			$this->addPublishPostMetaBoxHiddenFields($name, ['type' => 'hidden', 'value' => $id]);
2540
+		}
2541
+		$hidden_fields = $this->_generate_admin_form_fields($this->publish_post_meta_box_hidden_fields, 'array');
2542
+		// add hidden fields
2543
+		$this->_template_args['publish_hidden_fields'] = $this->_template_args['publish_hidden_fields'] ?? '';
2544
+		foreach ($hidden_fields as $hidden_field) {
2545
+			$this->_template_args['publish_hidden_fields'] .= $hidden_field['field'] ?? '';
2546
+		}
2547
+	}
2548
+
2549
+
2550
+	/**
2551
+	 * @param string|null $name
2552
+	 * @param int|string  $id
2553
+	 * @param string|null $delete
2554
+	 * @param string|null $save_close_redirect_URL
2555
+	 * @param bool        $both_btns
2556
+	 * @throws EE_Error
2557
+	 */
2558
+	public function set_publish_post_box_vars(
2559
+		?string $name = '',
2560
+		$id = 0,
2561
+		?string $delete = '',
2562
+		?string $save_close_redirect_URL = '',
2563
+		bool $both_btns = false
2564
+	) {
2565
+		$this->_set_publish_post_box_vars($name, $id, $delete, $save_close_redirect_URL, $both_btns);
2566
+	}
2567
+
2568
+
2569
+	protected function addPublishPostMetaBoxHiddenFields(string $field_name, array $field_attributes)
2570
+	{
2571
+		$this->publish_post_meta_box_hidden_fields[ $field_name ] = $field_attributes;
2572
+	}
2573
+
2574
+
2575
+	/**
2576
+	 * displays an error message to ppl who have javascript disabled
2577
+	 *
2578
+	 * @return void
2579
+	 */
2580
+	private function _display_no_javascript_warning()
2581
+	{
2582
+		?>
2583 2583
 <noscript>
2584 2584
     <div id="no-js-message" class="error">
2585 2585
         <p style="font-size:1.3em;">
2586 2586
             <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2587 2587
             <?php esc_html_e(
2588
-                'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2589
-                'event_espresso'
2590
-            ); ?>
2588
+				'Javascript is currently turned off for your browser. Javascript must be enabled in order for all of the features on this page to function properly. Please turn your javascript back on.',
2589
+				'event_espresso'
2590
+			); ?>
2591 2591
         </p>
2592 2592
     </div>
2593 2593
 </noscript>
2594 2594
 <?php
2595
-    }
2596
-
2597
-
2598
-    /**
2599
-     * displays espresso success and/or error notices
2600
-     *
2601
-     * @return void
2602
-     */
2603
-    protected function _display_espresso_notices()
2604
-    {
2605
-        $notices = (array) $this->_get_transient(true);
2606
-        foreach ($notices as $notice) {
2607
-            echo $notice ? stripslashes($notice) : '';
2608
-        }
2609
-    }
2610
-
2611
-
2612
-    /**
2613
-     * spinny things pacify the masses
2614
-     *
2615
-     * @return void
2616
-     */
2617
-    protected function _add_admin_page_ajax_loading_img()
2618
-    {
2619
-        ?>
2595
+	}
2596
+
2597
+
2598
+	/**
2599
+	 * displays espresso success and/or error notices
2600
+	 *
2601
+	 * @return void
2602
+	 */
2603
+	protected function _display_espresso_notices()
2604
+	{
2605
+		$notices = (array) $this->_get_transient(true);
2606
+		foreach ($notices as $notice) {
2607
+			echo $notice ? stripslashes($notice) : '';
2608
+		}
2609
+	}
2610
+
2611
+
2612
+	/**
2613
+	 * spinny things pacify the masses
2614
+	 *
2615
+	 * @return void
2616
+	 */
2617
+	protected function _add_admin_page_ajax_loading_img()
2618
+	{
2619
+		?>
2620 2620
 <div id="espresso-ajax-loading" class="ajax-loading-grey">
2621 2621
     <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2622
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2622
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2623 2623
 </div>
2624 2624
 <?php
2625
-    }
2625
+	}
2626 2626
 
2627 2627
 
2628
-    /**
2629
-     * add admin page overlay for modal boxes
2630
-     *
2631
-     * @return void
2632
-     */
2633
-    protected function _add_admin_page_overlay()
2634
-    {
2635
-        ?>
2628
+	/**
2629
+	 * add admin page overlay for modal boxes
2630
+	 *
2631
+	 * @return void
2632
+	 */
2633
+	protected function _add_admin_page_overlay()
2634
+	{
2635
+		?>
2636 2636
 <div id="espresso-admin-page-overlay-dv" class=""></div>
2637 2637
 <?php
2638
-    }
2639
-
2640
-
2641
-    /**
2642
-     * facade for $this->addMetaBox()
2643
-     *
2644
-     * @param string   $action        where the metabox gets displayed
2645
-     * @param string   $title         Title of Metabox (output in metabox header)
2646
-     * @param callable $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2647
-     *                                instead of the one created in here.
2648
-     * @param array    $callback_args an array of args supplied for the metabox
2649
-     * @param string   $column        what metabox column
2650
-     * @param string   $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2651
-     * @param bool     $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2652
-     *                                created but just set our own callback for wp's add_meta_box.
2653
-     * @throws DomainException
2654
-     */
2655
-    public function _add_admin_page_meta_box(
2656
-        string $action,
2657
-        string $title,
2658
-        callable $callback,
2659
-        array $callback_args,
2660
-        string $column = 'normal',
2661
-        string $priority = 'high',
2662
-        bool $create_func = true
2663
-    ) {
2664
-        // 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.
2665
-        if (empty($callback_args) && $create_func) {
2666
-            $callback_args = [
2667
-                'template_path' => $this->_template_path,
2668
-                'template_args' => $this->_template_args,
2669
-            ];
2670
-        }
2671
-        // 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)
2672
-        $call_back_func = $create_func
2673
-            ? static function ($post, $metabox) {
2674
-                echo EEH_Template::display_template(
2675
-                    $metabox['args']['template_path'],
2676
-                    $metabox['args']['template_args'],
2677
-                    true
2678
-                );
2679
-            }
2680
-            : $callback;
2681
-        $this->addMetaBox(
2682
-            str_replace('_', '-', $action) . '-mbox',
2683
-            $title,
2684
-            $call_back_func,
2685
-            $this->_wp_page_slug,
2686
-            $column,
2687
-            $priority,
2688
-            $callback_args
2689
-        );
2690
-    }
2691
-
2692
-
2693
-    /**
2694
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2695
-     *
2696
-     * @throws DomainException
2697
-     * @throws EE_Error
2698
-     * @throws InvalidArgumentException
2699
-     * @throws InvalidDataTypeException
2700
-     * @throws InvalidInterfaceException
2701
-     */
2702
-    public function display_admin_page_with_metabox_columns()
2703
-    {
2704
-        $this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2705
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2706
-            $this->_column_template_path,
2707
-            $this->_template_args,
2708
-            true
2709
-        );
2710
-        // the final wrapper
2711
-        $this->admin_page_wrapper();
2712
-    }
2713
-
2714
-
2715
-    /**
2716
-     * generates  HTML wrapper for an admin details page
2717
-     *
2718
-     * @return void
2719
-     * @throws DomainException
2720
-     * @throws EE_Error
2721
-     * @throws InvalidArgumentException
2722
-     * @throws InvalidDataTypeException
2723
-     * @throws InvalidInterfaceException
2724
-     */
2725
-    public function display_admin_page_with_sidebar()
2726
-    {
2727
-        $this->_display_admin_page(true);
2728
-    }
2729
-
2730
-
2731
-    /**
2732
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2733
-     *
2734
-     * @return void
2735
-     * @throws DomainException
2736
-     * @throws EE_Error
2737
-     * @throws InvalidArgumentException
2738
-     * @throws InvalidDataTypeException
2739
-     * @throws InvalidInterfaceException
2740
-     */
2741
-    public function display_admin_page_with_no_sidebar()
2742
-    {
2743
-        $this->_display_admin_page();
2744
-    }
2745
-
2746
-
2747
-    /**
2748
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2749
-     *
2750
-     * @return void
2751
-     * @throws DomainException
2752
-     * @throws EE_Error
2753
-     * @throws InvalidArgumentException
2754
-     * @throws InvalidDataTypeException
2755
-     * @throws InvalidInterfaceException
2756
-     */
2757
-    public function display_about_admin_page()
2758
-    {
2759
-        $this->_display_admin_page(false, true);
2760
-    }
2761
-
2762
-
2763
-    /**
2764
-     * display_admin_page
2765
-     * contains the code for actually displaying an admin page
2766
-     *
2767
-     * @param bool $sidebar true with sidebar, false without
2768
-     * @param bool $about   use the About admin wrapper instead of the default.
2769
-     * @return void
2770
-     * @throws DomainException
2771
-     * @throws EE_Error
2772
-     * @throws InvalidArgumentException
2773
-     * @throws InvalidDataTypeException
2774
-     * @throws InvalidInterfaceException
2775
-     */
2776
-    private function _display_admin_page(bool $sidebar = false, bool $about = false): void
2777
-    {
2778
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2779
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2780
-
2781
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2782
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2783
-        $post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2784
-
2785
-        $this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2786
-                                                  && $this->_req_action !== 'data_reset'
2787
-                                                  && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2788
-                                                  && strpos($post_body_content, 'wp-list-table') === false;
2789
-
2790
-        $this->_template_args['current_page']                 = $this->_wp_page_slug;
2791
-        $this->_template_args['admin_page_wrapper_div_id']    = $this->_cpt_route
2792
-            ? 'poststuff'
2793
-            : 'espresso-default-admin';
2794
-        $this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2795
-            'event-espresso_page_espresso_',
2796
-            '',
2797
-            $this->_wp_page_slug
2798
-        ) . ' ' . $this->_req_action . '-route';
2799
-
2800
-        $template_path = $sidebar
2801
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2802
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2803
-
2804
-        $this->_template_args['is_ajax'] = $this->request->isAjax();
2805
-        if ($this->request->isAjax()) {
2806
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2807
-        }
2808
-        $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2809
-
2810
-        $this->_template_args['post_body_content']         = $this->_template_args['admin_page_content'] ?? '';
2811
-        $this->_template_args['before_admin_page_content'] = $post_body_content;
2812
-        $this->_template_args['after_admin_page_content']  = $this->_template_args['after_admin_page_content'] ?? '';
2813
-
2814
-        // ensure $post_type and $post are set
2815
-        // to prevent WooCommerce from blowing things up if not using CPT
2816
-        global $post_type, $post;
2817
-        $this->_template_args['post_type'] = $post_type ?? '';
2818
-        $this->_template_args['post']  = $post ?? new WP_Post((object) [ 'ID' => 0, 'filter' => 'raw' ]);
2819
-
2820
-        $this->_template_args['post_body_content'] = EEH_Template::display_template(
2821
-            EE_ADMIN_TEMPLATE . 'admin_details_wrapper_post_body_content.template.php',
2822
-            $this->_template_args,
2823
-            true
2824
-        );
2825
-
2826
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2827
-            $template_path,
2828
-            $this->_template_args,
2829
-            true
2830
-        );
2831
-        // the final template wrapper
2832
-        $this->admin_page_wrapper($about);
2833
-    }
2834
-
2835
-
2836
-    /**
2837
-     * This is used to display caf preview pages.
2838
-     *
2839
-     * @param string $utm_campaign_source what is the key used for Google Analytics link
2840
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2841
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2842
-     * @return void
2843
-     * @throws DomainException
2844
-     * @throws EE_Error
2845
-     * @throws InvalidArgumentException
2846
-     * @throws InvalidDataTypeException
2847
-     * @throws InvalidInterfaceException
2848
-     * @since 4.3.2
2849
-     */
2850
-    public function display_admin_caf_preview_page(string $utm_campaign_source = '', bool $display_sidebar = true)
2851
-    {
2852
-        // let's generate a default preview action button if there isn't one already present.
2853
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2854
-            'Upgrade to Event Espresso 4 Right Now',
2855
-            'event_espresso'
2856
-        );
2857
-        $buy_now_url                                   = add_query_arg(
2858
-            [
2859
-                'ee_ver'       => 'ee4',
2860
-                'utm_source'   => 'ee4_plugin_admin',
2861
-                'utm_medium'   => 'link',
2862
-                'utm_campaign' => $utm_campaign_source,
2863
-                'utm_content'  => 'buy_now_button',
2864
-            ],
2865
-            'https://eventespresso.com/pricing/'
2866
-        );
2867
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2868
-            ? $this->get_action_link_or_button(
2869
-                '',
2870
-                'buy_now',
2871
-                [],
2872
-                'button button--primary button--big',
2873
-                esc_url_raw($buy_now_url),
2874
-                true
2875
-            )
2876
-            : $this->_template_args['preview_action_button'];
2877
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2878
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2879
-            $this->_template_args,
2880
-            true
2881
-        );
2882
-        $this->_display_admin_page($display_sidebar);
2883
-    }
2884
-
2885
-
2886
-    /**
2887
-     * display_admin_list_table_page_with_sidebar
2888
-     * generates HTML wrapper for an admin_page with list_table
2889
-     *
2890
-     * @return void
2891
-     * @throws DomainException
2892
-     * @throws EE_Error
2893
-     * @throws InvalidArgumentException
2894
-     * @throws InvalidDataTypeException
2895
-     * @throws InvalidInterfaceException
2896
-     */
2897
-    public function display_admin_list_table_page_with_sidebar()
2898
-    {
2899
-        $this->_display_admin_list_table_page(true);
2900
-    }
2901
-
2902
-
2903
-    /**
2904
-     * display_admin_list_table_page_with_no_sidebar
2905
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2906
-     *
2907
-     * @return void
2908
-     * @throws DomainException
2909
-     * @throws EE_Error
2910
-     * @throws InvalidArgumentException
2911
-     * @throws InvalidDataTypeException
2912
-     * @throws InvalidInterfaceException
2913
-     */
2914
-    public function display_admin_list_table_page_with_no_sidebar()
2915
-    {
2916
-        $this->_display_admin_list_table_page();
2917
-    }
2918
-
2919
-
2920
-    /**
2921
-     * generates html wrapper for an admin_list_table page
2922
-     *
2923
-     * @param bool $sidebar whether to display with sidebar or not.
2924
-     * @return void
2925
-     * @throws DomainException
2926
-     * @throws EE_Error
2927
-     * @throws InvalidArgumentException
2928
-     * @throws InvalidDataTypeException
2929
-     * @throws InvalidInterfaceException
2930
-     */
2931
-    private function _display_admin_list_table_page(bool $sidebar = false)
2932
-    {
2933
-        // setup search attributes
2934
-        $this->_set_search_attributes();
2935
-        $this->_template_args['current_page']     = $this->_wp_page_slug;
2936
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2937
-        $this->_template_args['table_url']        = $this->request->isAjax()
2938
-            ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2939
-            : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2940
-        $this->_template_args['list_table']       = $this->_list_table_object;
2941
-        $this->_template_args['current_route']    = $this->_req_action;
2942
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2943
-        $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2944
-        if (! empty($ajax_sorting_callback)) {
2945
-            $sortable_list_table_form_fields = wp_nonce_field(
2946
-                $ajax_sorting_callback . '_nonce',
2947
-                $ajax_sorting_callback . '_nonce',
2948
-                false,
2949
-                false
2950
-            );
2951
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2952
-                                                . $this->page_slug
2953
-                                                . '" />';
2954
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2955
-                                                . $ajax_sorting_callback
2956
-                                                . '" />';
2957
-        } else {
2958
-            $sortable_list_table_form_fields = '';
2959
-        }
2960
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2961
-
2962
-        $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2963
-
2964
-        $nonce_ref          = $this->_req_action . '_nonce';
2965
-        $hidden_form_fields .= '
2638
+	}
2639
+
2640
+
2641
+	/**
2642
+	 * facade for $this->addMetaBox()
2643
+	 *
2644
+	 * @param string   $action        where the metabox gets displayed
2645
+	 * @param string   $title         Title of Metabox (output in metabox header)
2646
+	 * @param callable $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2647
+	 *                                instead of the one created in here.
2648
+	 * @param array    $callback_args an array of args supplied for the metabox
2649
+	 * @param string   $column        what metabox column
2650
+	 * @param string   $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2651
+	 * @param bool     $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2652
+	 *                                created but just set our own callback for wp's add_meta_box.
2653
+	 * @throws DomainException
2654
+	 */
2655
+	public function _add_admin_page_meta_box(
2656
+		string $action,
2657
+		string $title,
2658
+		callable $callback,
2659
+		array $callback_args,
2660
+		string $column = 'normal',
2661
+		string $priority = 'high',
2662
+		bool $create_func = true
2663
+	) {
2664
+		// 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.
2665
+		if (empty($callback_args) && $create_func) {
2666
+			$callback_args = [
2667
+				'template_path' => $this->_template_path,
2668
+				'template_args' => $this->_template_args,
2669
+			];
2670
+		}
2671
+		// 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)
2672
+		$call_back_func = $create_func
2673
+			? static function ($post, $metabox) {
2674
+				echo EEH_Template::display_template(
2675
+					$metabox['args']['template_path'],
2676
+					$metabox['args']['template_args'],
2677
+					true
2678
+				);
2679
+			}
2680
+			: $callback;
2681
+		$this->addMetaBox(
2682
+			str_replace('_', '-', $action) . '-mbox',
2683
+			$title,
2684
+			$call_back_func,
2685
+			$this->_wp_page_slug,
2686
+			$column,
2687
+			$priority,
2688
+			$callback_args
2689
+		);
2690
+	}
2691
+
2692
+
2693
+	/**
2694
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2695
+	 *
2696
+	 * @throws DomainException
2697
+	 * @throws EE_Error
2698
+	 * @throws InvalidArgumentException
2699
+	 * @throws InvalidDataTypeException
2700
+	 * @throws InvalidInterfaceException
2701
+	 */
2702
+	public function display_admin_page_with_metabox_columns()
2703
+	{
2704
+		$this->_template_args['post_body_content']  = $this->_template_args['admin_page_content'];
2705
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2706
+			$this->_column_template_path,
2707
+			$this->_template_args,
2708
+			true
2709
+		);
2710
+		// the final wrapper
2711
+		$this->admin_page_wrapper();
2712
+	}
2713
+
2714
+
2715
+	/**
2716
+	 * generates  HTML wrapper for an admin details page
2717
+	 *
2718
+	 * @return void
2719
+	 * @throws DomainException
2720
+	 * @throws EE_Error
2721
+	 * @throws InvalidArgumentException
2722
+	 * @throws InvalidDataTypeException
2723
+	 * @throws InvalidInterfaceException
2724
+	 */
2725
+	public function display_admin_page_with_sidebar()
2726
+	{
2727
+		$this->_display_admin_page(true);
2728
+	}
2729
+
2730
+
2731
+	/**
2732
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2733
+	 *
2734
+	 * @return void
2735
+	 * @throws DomainException
2736
+	 * @throws EE_Error
2737
+	 * @throws InvalidArgumentException
2738
+	 * @throws InvalidDataTypeException
2739
+	 * @throws InvalidInterfaceException
2740
+	 */
2741
+	public function display_admin_page_with_no_sidebar()
2742
+	{
2743
+		$this->_display_admin_page();
2744
+	}
2745
+
2746
+
2747
+	/**
2748
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2749
+	 *
2750
+	 * @return void
2751
+	 * @throws DomainException
2752
+	 * @throws EE_Error
2753
+	 * @throws InvalidArgumentException
2754
+	 * @throws InvalidDataTypeException
2755
+	 * @throws InvalidInterfaceException
2756
+	 */
2757
+	public function display_about_admin_page()
2758
+	{
2759
+		$this->_display_admin_page(false, true);
2760
+	}
2761
+
2762
+
2763
+	/**
2764
+	 * display_admin_page
2765
+	 * contains the code for actually displaying an admin page
2766
+	 *
2767
+	 * @param bool $sidebar true with sidebar, false without
2768
+	 * @param bool $about   use the About admin wrapper instead of the default.
2769
+	 * @return void
2770
+	 * @throws DomainException
2771
+	 * @throws EE_Error
2772
+	 * @throws InvalidArgumentException
2773
+	 * @throws InvalidDataTypeException
2774
+	 * @throws InvalidInterfaceException
2775
+	 */
2776
+	private function _display_admin_page(bool $sidebar = false, bool $about = false): void
2777
+	{
2778
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2779
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2780
+
2781
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2782
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2783
+		$post_body_content = $this->_template_args['before_admin_page_content'] ?? '';
2784
+
2785
+		$this->_template_args['add_page_frame'] = $this->_req_action !== 'system_status'
2786
+												  && $this->_req_action !== 'data_reset'
2787
+												  && $this->_wp_page_slug !== 'event-espresso_page_espresso_packages'
2788
+												  && strpos($post_body_content, 'wp-list-table') === false;
2789
+
2790
+		$this->_template_args['current_page']                 = $this->_wp_page_slug;
2791
+		$this->_template_args['admin_page_wrapper_div_id']    = $this->_cpt_route
2792
+			? 'poststuff'
2793
+			: 'espresso-default-admin';
2794
+		$this->_template_args['admin_page_wrapper_div_class'] = str_replace(
2795
+			'event-espresso_page_espresso_',
2796
+			'',
2797
+			$this->_wp_page_slug
2798
+		) . ' ' . $this->_req_action . '-route';
2799
+
2800
+		$template_path = $sidebar
2801
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2802
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2803
+
2804
+		$this->_template_args['is_ajax'] = $this->request->isAjax();
2805
+		if ($this->request->isAjax()) {
2806
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2807
+		}
2808
+		$template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2809
+
2810
+		$this->_template_args['post_body_content']         = $this->_template_args['admin_page_content'] ?? '';
2811
+		$this->_template_args['before_admin_page_content'] = $post_body_content;
2812
+		$this->_template_args['after_admin_page_content']  = $this->_template_args['after_admin_page_content'] ?? '';
2813
+
2814
+		// ensure $post_type and $post are set
2815
+		// to prevent WooCommerce from blowing things up if not using CPT
2816
+		global $post_type, $post;
2817
+		$this->_template_args['post_type'] = $post_type ?? '';
2818
+		$this->_template_args['post']  = $post ?? new WP_Post((object) [ 'ID' => 0, 'filter' => 'raw' ]);
2819
+
2820
+		$this->_template_args['post_body_content'] = EEH_Template::display_template(
2821
+			EE_ADMIN_TEMPLATE . 'admin_details_wrapper_post_body_content.template.php',
2822
+			$this->_template_args,
2823
+			true
2824
+		);
2825
+
2826
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2827
+			$template_path,
2828
+			$this->_template_args,
2829
+			true
2830
+		);
2831
+		// the final template wrapper
2832
+		$this->admin_page_wrapper($about);
2833
+	}
2834
+
2835
+
2836
+	/**
2837
+	 * This is used to display caf preview pages.
2838
+	 *
2839
+	 * @param string $utm_campaign_source what is the key used for Google Analytics link
2840
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2841
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2842
+	 * @return void
2843
+	 * @throws DomainException
2844
+	 * @throws EE_Error
2845
+	 * @throws InvalidArgumentException
2846
+	 * @throws InvalidDataTypeException
2847
+	 * @throws InvalidInterfaceException
2848
+	 * @since 4.3.2
2849
+	 */
2850
+	public function display_admin_caf_preview_page(string $utm_campaign_source = '', bool $display_sidebar = true)
2851
+	{
2852
+		// let's generate a default preview action button if there isn't one already present.
2853
+		$this->_labels['buttons']['buy_now']           = esc_html__(
2854
+			'Upgrade to Event Espresso 4 Right Now',
2855
+			'event_espresso'
2856
+		);
2857
+		$buy_now_url                                   = add_query_arg(
2858
+			[
2859
+				'ee_ver'       => 'ee4',
2860
+				'utm_source'   => 'ee4_plugin_admin',
2861
+				'utm_medium'   => 'link',
2862
+				'utm_campaign' => $utm_campaign_source,
2863
+				'utm_content'  => 'buy_now_button',
2864
+			],
2865
+			'https://eventespresso.com/pricing/'
2866
+		);
2867
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2868
+			? $this->get_action_link_or_button(
2869
+				'',
2870
+				'buy_now',
2871
+				[],
2872
+				'button button--primary button--big',
2873
+				esc_url_raw($buy_now_url),
2874
+				true
2875
+			)
2876
+			: $this->_template_args['preview_action_button'];
2877
+		$this->_template_args['admin_page_content']    = EEH_Template::display_template(
2878
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2879
+			$this->_template_args,
2880
+			true
2881
+		);
2882
+		$this->_display_admin_page($display_sidebar);
2883
+	}
2884
+
2885
+
2886
+	/**
2887
+	 * display_admin_list_table_page_with_sidebar
2888
+	 * generates HTML wrapper for an admin_page with list_table
2889
+	 *
2890
+	 * @return void
2891
+	 * @throws DomainException
2892
+	 * @throws EE_Error
2893
+	 * @throws InvalidArgumentException
2894
+	 * @throws InvalidDataTypeException
2895
+	 * @throws InvalidInterfaceException
2896
+	 */
2897
+	public function display_admin_list_table_page_with_sidebar()
2898
+	{
2899
+		$this->_display_admin_list_table_page(true);
2900
+	}
2901
+
2902
+
2903
+	/**
2904
+	 * display_admin_list_table_page_with_no_sidebar
2905
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2906
+	 *
2907
+	 * @return void
2908
+	 * @throws DomainException
2909
+	 * @throws EE_Error
2910
+	 * @throws InvalidArgumentException
2911
+	 * @throws InvalidDataTypeException
2912
+	 * @throws InvalidInterfaceException
2913
+	 */
2914
+	public function display_admin_list_table_page_with_no_sidebar()
2915
+	{
2916
+		$this->_display_admin_list_table_page();
2917
+	}
2918
+
2919
+
2920
+	/**
2921
+	 * generates html wrapper for an admin_list_table page
2922
+	 *
2923
+	 * @param bool $sidebar whether to display with sidebar or not.
2924
+	 * @return void
2925
+	 * @throws DomainException
2926
+	 * @throws EE_Error
2927
+	 * @throws InvalidArgumentException
2928
+	 * @throws InvalidDataTypeException
2929
+	 * @throws InvalidInterfaceException
2930
+	 */
2931
+	private function _display_admin_list_table_page(bool $sidebar = false)
2932
+	{
2933
+		// setup search attributes
2934
+		$this->_set_search_attributes();
2935
+		$this->_template_args['current_page']     = $this->_wp_page_slug;
2936
+		$template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2937
+		$this->_template_args['table_url']        = $this->request->isAjax()
2938
+			? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2939
+			: add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
2940
+		$this->_template_args['list_table']       = $this->_list_table_object;
2941
+		$this->_template_args['current_route']    = $this->_req_action;
2942
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2943
+		$ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2944
+		if (! empty($ajax_sorting_callback)) {
2945
+			$sortable_list_table_form_fields = wp_nonce_field(
2946
+				$ajax_sorting_callback . '_nonce',
2947
+				$ajax_sorting_callback . '_nonce',
2948
+				false,
2949
+				false
2950
+			);
2951
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2952
+												. $this->page_slug
2953
+												. '" />';
2954
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2955
+												. $ajax_sorting_callback
2956
+												. '" />';
2957
+		} else {
2958
+			$sortable_list_table_form_fields = '';
2959
+		}
2960
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2961
+
2962
+		$hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2963
+
2964
+		$nonce_ref          = $this->_req_action . '_nonce';
2965
+		$hidden_form_fields .= '
2966 2966
             <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2967 2967
 
2968
-        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2969
-        // display message about search results?
2970
-        $search                                    = $this->request->getRequestParam('s');
2971
-        $this->_template_args['before_list_table'] .= ! empty($search)
2972
-            ? '<p class="ee-search-results">' . sprintf(
2973
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2974
-                trim($search, '%')
2975
-            ) . '</p>'
2976
-            : '';
2977
-        // filter before_list_table template arg
2978
-        $this->_template_args['before_list_table'] = apply_filters(
2979
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2980
-            $this->_template_args['before_list_table'],
2981
-            $this->page_slug,
2982
-            $this->request->requestParams(),
2983
-            $this->_req_action
2984
-        );
2985
-        // convert to array and filter again
2986
-        // arrays are easier to inject new items in a specific location,
2987
-        // but would not be backwards compatible, so we have to add a new filter
2988
-        $this->_template_args['before_list_table'] = implode(
2989
-            " \n",
2990
-            (array) apply_filters(
2991
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2992
-                (array) $this->_template_args['before_list_table'],
2993
-                $this->page_slug,
2994
-                $this->request->requestParams(),
2995
-                $this->_req_action
2996
-            )
2997
-        );
2998
-        // filter after_list_table template arg
2999
-        $this->_template_args['after_list_table'] = apply_filters(
3000
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3001
-            $this->_template_args['after_list_table'],
3002
-            $this->page_slug,
3003
-            $this->request->requestParams(),
3004
-            $this->_req_action
3005
-        );
3006
-        // convert to array and filter again
3007
-        // arrays are easier to inject new items in a specific location,
3008
-        // but would not be backwards compatible, so we have to add a new filter
3009
-        $this->_template_args['after_list_table']   = implode(
3010
-            " \n",
3011
-            (array) apply_filters(
3012
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3013
-                (array) $this->_template_args['after_list_table'],
3014
-                $this->page_slug,
3015
-                $this->request->requestParams(),
3016
-                $this->_req_action
3017
-            )
3018
-        );
3019
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3020
-            $template_path,
3021
-            $this->_template_args,
3022
-            true
3023
-        );
3024
-        // the final template wrapper
3025
-        if ($sidebar) {
3026
-            $this->display_admin_page_with_sidebar();
3027
-        } else {
3028
-            $this->display_admin_page_with_no_sidebar();
3029
-        }
3030
-    }
3031
-
3032
-
3033
-    /**
3034
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3035
-     * html string for the legend.
3036
-     * $items are expected in an array in the following format:
3037
-     * $legend_items = array(
3038
-     *        'item_id' => array(
3039
-     *            'icon' => 'http://url_to_icon_being_described.png',
3040
-     *            'desc' => esc_html__('localized description of item');
3041
-     *        )
3042
-     * );
3043
-     *
3044
-     * @param array $items see above for format of array
3045
-     * @return string html string of legend
3046
-     * @throws DomainException
3047
-     */
3048
-    protected function _display_legend(array $items): string
3049
-    {
3050
-        $this->_template_args['items'] = (array) apply_filters(
3051
-            'FHEE__EE_Admin_Page___display_legend__items',
3052
-            $items,
3053
-            $this
3054
-        );
3055
-        /** @var StatusChangeNotice $status_change_notice */
3056
-        $status_change_notice                         = $this->loader->getShared(
3057
-            'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3058
-        );
3059
-        $this->_template_args['status_change_notice'] = $status_change_notice->display(
3060
-            '__admin-legend',
3061
-            $this->page_slug
3062
-        );
3063
-        return EEH_Template::display_template(
3064
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3065
-            $this->_template_args,
3066
-            true
3067
-        );
3068
-    }
3069
-
3070
-
3071
-    /**
3072
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3073
-     * The returned json object is created from an array in the following format:
3074
-     * array(
3075
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3076
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3077
-     *  'notices' => '', // - contains any EE_Error formatted notices
3078
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3079
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3080
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3081
-     *  that might be included in here)
3082
-     * )
3083
-     * The json object is populated by whatever is set in the $_template_args property.
3084
-     *
3085
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3086
-     *                                 instead of displayed.
3087
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3088
-     * @return void
3089
-     * @throws EE_Error
3090
-     * @throws InvalidArgumentException
3091
-     * @throws InvalidDataTypeException
3092
-     * @throws InvalidInterfaceException
3093
-     */
3094
-    protected function _return_json(bool $sticky_notices = false, array $notices_arguments = [])
3095
-    {
3096
-        // make sure any EE_Error notices have been handled.
3097
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3098
-        $data = $this->_template_args['data'] ?? [];
3099
-        unset($this->_template_args['data']);
3100
-        $json = [
3101
-            'error'     => $this->_template_args['error'] ?? false,
3102
-            'success'   => $this->_template_args['success'] ?? false,
3103
-            'errors'    => $this->_template_args['errors'] ?? false,
3104
-            'attention' => $this->_template_args['attention'] ?? false,
3105
-            'notices'   => EE_Error::get_notices(),
3106
-            'content'   => $this->_template_args['admin_page_content'] ?? '',
3107
-            'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3108
-            'isEEajax'  => true,
3109
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3110
-        ];
3111
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3112
-        if (null === error_get_last() || ! headers_sent()) {
3113
-            header('Content-Type: application/json; charset=UTF-8');
3114
-        }
3115
-        echo wp_json_encode($json);
3116
-        exit();
3117
-    }
3118
-
3119
-
3120
-    /**
3121
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3122
-     *
3123
-     * @return void
3124
-     * @throws EE_Error
3125
-     * @throws InvalidArgumentException
3126
-     * @throws InvalidDataTypeException
3127
-     * @throws InvalidInterfaceException
3128
-     */
3129
-    public function return_json()
3130
-    {
3131
-        if ($this->request->isAjax()) {
3132
-            $this->_return_json();
3133
-        } else {
3134
-            throw new EE_Error(
3135
-                sprintf(
3136
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3137
-                    __FUNCTION__
3138
-                )
3139
-            );
3140
-        }
3141
-    }
3142
-
3143
-
3144
-    /**
3145
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3146
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3147
-     *
3148
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3149
-     * @deprecated  5.0.8.p
3150
-     */
3151
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3152
-    {
3153
-        $this->_hook_obj = $hook_obj;
3154
-    }
3155
-
3156
-
3157
-    /**
3158
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3159
-     *
3160
-     * @param bool $about whether to use the special about page wrapper or default.
3161
-     * @return void
3162
-     * @throws DomainException
3163
-     * @throws EE_Error
3164
-     * @throws InvalidArgumentException
3165
-     * @throws InvalidDataTypeException
3166
-     * @throws InvalidInterfaceException
3167
-     */
3168
-    public function admin_page_wrapper(bool $about = false)
3169
-    {
3170
-        $this->_template_args['nav_tabs']         = $this->_get_main_nav_tabs();
3171
-        $this->_template_args['admin_page_title'] = $this->_admin_page_title;
3172
-
3173
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3174
-            "FHEE_before_admin_page_content$this->_current_page$this->_current_view",
3175
-            $this->_template_args['before_admin_page_content'] ?? ''
3176
-        );
3177
-
3178
-        $this->_template_args['after_admin_page_content'] = apply_filters(
3179
-            "FHEE_after_admin_page_content$this->_current_page$this->_current_view",
3180
-            $this->_template_args['after_admin_page_content'] ?? ''
3181
-        );
3182
-        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3183
-
3184
-        if ($this->request->isAjax()) {
3185
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3186
-            // $template_path,
3187
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3188
-                $this->_template_args,
3189
-                true
3190
-            );
3191
-            $this->_return_json();
3192
-        }
3193
-        // load settings page wrapper template
3194
-        $template_path = $about
3195
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3196
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3197
-
3198
-        EEH_Template::display_template($template_path, $this->_template_args);
3199
-    }
3200
-
3201
-
3202
-    /**
3203
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3204
-     *
3205
-     * @return string html
3206
-     * @throws EE_Error
3207
-     */
3208
-    protected function _get_main_nav_tabs(): string
3209
-    {
3210
-        // let's generate the html using the EEH_Tabbed_Content helper.
3211
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3212
-        // (rather than setting in the page_routes array)
3213
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs, $this->page_slug);
3214
-    }
3215
-
3216
-
3217
-    /**
3218
-     *        sort nav tabs
3219
-     *
3220
-     * @param array $a
3221
-     * @param array $b
3222
-     * @return int
3223
-     */
3224
-    private function _sort_nav_tabs(array $a, array $b): int
3225
-    {
3226
-        if ($a['order'] === $b['order']) {
3227
-            return 0;
3228
-        }
3229
-        return ($a['order'] < $b['order']) ? -1 : 1;
3230
-    }
3231
-
3232
-
3233
-    /**
3234
-     * generates HTML for the forms used on admin pages
3235
-     *
3236
-     * @param array  $input_vars - array of input field details
3237
-     * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3238
-     * @param bool   $id
3239
-     * @return array|string
3240
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3241
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3242
-     */
3243
-    protected function _generate_admin_form_fields(
3244
-        array $input_vars = [],
3245
-        string $generator = 'string',
3246
-        bool $id = false
3247
-    ) {
3248
-        return $generator === 'string'
3249
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3250
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3251
-    }
3252
-
3253
-
3254
-    /**
3255
-     * generates the "Save" and "Save & Close" buttons for edit forms
3256
-     *
3257
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3258
-     *                                   Close" button.
3259
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3260
-     *                                   'Save', [1] => 'save & close')
3261
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3262
-     *                                   via the "name" value in the button).  We can also use this to just dump
3263
-     *                                   default actions by submitting some other value.
3264
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Otherwise it
3265
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3266
-     *                                   close (normal form handling).
3267
-     */
3268
-    protected function _set_save_buttons(bool $both = true, array $text = [], array $actions = [], $referrer = null)
3269
-    {
3270
-        $referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3271
-        $button_text   = ! empty($text)
3272
-            ? $text
3273
-            : [
3274
-                esc_html__('Save', 'event_espresso'),
3275
-                esc_html__('Save and Close', 'event_espresso'),
3276
-            ];
3277
-        $default_names = ['save', 'save_and_close'];
3278
-        $buttons       = '';
3279
-        foreach ($button_text as $key => $button) {
3280
-            $ref     = $default_names[ $key ];
3281
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3282
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3283
-                        . 'value="' . $button . '" name="' . $name . '" '
3284
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3285
-            if (! $both) {
3286
-                break;
3287
-            }
3288
-        }
3289
-        // add in a hidden index for the current page (so save and close redirects properly)
3290
-        $buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3291
-                    . $referrer_url
3292
-                    . '" />';
3293
-
3294
-        $this->_template_args['save_buttons'] = $buttons;
3295
-    }
3296
-
3297
-
3298
-    /**
3299
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3300
-     *
3301
-     * @param string $route
3302
-     * @param array  $additional_hidden_fields
3303
-     * @see   $this->_set_add_edit_form_tags() for details on params
3304
-     * @since 4.6.0
3305
-     */
3306
-    public function set_add_edit_form_tags(string $route = '', array $additional_hidden_fields = [])
3307
-    {
3308
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3309
-    }
3310
-
3311
-
3312
-    /**
3313
-     * set form open and close tags on add/edit pages.
3314
-     *
3315
-     * @param string $route                    the route you want the form to direct to
3316
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3317
-     * @return void
3318
-     */
3319
-    protected function _set_add_edit_form_tags(string $route = '', array $additional_hidden_fields = [])
3320
-    {
3321
-        if (empty($route)) {
3322
-            $user_msg = esc_html__(
3323
-                'An error occurred. No action was set for this page\'s form.',
3324
-                'event_espresso'
3325
-            );
3326
-            $dev_msg  = $user_msg . "\n"
3327
-                        . sprintf(
3328
-                            esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3329
-                            __FUNCTION__,
3330
-                            __CLASS__
3331
-                        );
3332
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3333
-        }
3334
-        // open form
3335
-        $action                                            = $this->_admin_base_url;
3336
-        $this->_template_args['before_admin_page_content'] = "
2968
+		$this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2969
+		// display message about search results?
2970
+		$search                                    = $this->request->getRequestParam('s');
2971
+		$this->_template_args['before_list_table'] .= ! empty($search)
2972
+			? '<p class="ee-search-results">' . sprintf(
2973
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2974
+				trim($search, '%')
2975
+			) . '</p>'
2976
+			: '';
2977
+		// filter before_list_table template arg
2978
+		$this->_template_args['before_list_table'] = apply_filters(
2979
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2980
+			$this->_template_args['before_list_table'],
2981
+			$this->page_slug,
2982
+			$this->request->requestParams(),
2983
+			$this->_req_action
2984
+		);
2985
+		// convert to array and filter again
2986
+		// arrays are easier to inject new items in a specific location,
2987
+		// but would not be backwards compatible, so we have to add a new filter
2988
+		$this->_template_args['before_list_table'] = implode(
2989
+			" \n",
2990
+			(array) apply_filters(
2991
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2992
+				(array) $this->_template_args['before_list_table'],
2993
+				$this->page_slug,
2994
+				$this->request->requestParams(),
2995
+				$this->_req_action
2996
+			)
2997
+		);
2998
+		// filter after_list_table template arg
2999
+		$this->_template_args['after_list_table'] = apply_filters(
3000
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
3001
+			$this->_template_args['after_list_table'],
3002
+			$this->page_slug,
3003
+			$this->request->requestParams(),
3004
+			$this->_req_action
3005
+		);
3006
+		// convert to array and filter again
3007
+		// arrays are easier to inject new items in a specific location,
3008
+		// but would not be backwards compatible, so we have to add a new filter
3009
+		$this->_template_args['after_list_table']   = implode(
3010
+			" \n",
3011
+			(array) apply_filters(
3012
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3013
+				(array) $this->_template_args['after_list_table'],
3014
+				$this->page_slug,
3015
+				$this->request->requestParams(),
3016
+				$this->_req_action
3017
+			)
3018
+		);
3019
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3020
+			$template_path,
3021
+			$this->_template_args,
3022
+			true
3023
+		);
3024
+		// the final template wrapper
3025
+		if ($sidebar) {
3026
+			$this->display_admin_page_with_sidebar();
3027
+		} else {
3028
+			$this->display_admin_page_with_no_sidebar();
3029
+		}
3030
+	}
3031
+
3032
+
3033
+	/**
3034
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3035
+	 * html string for the legend.
3036
+	 * $items are expected in an array in the following format:
3037
+	 * $legend_items = array(
3038
+	 *        'item_id' => array(
3039
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3040
+	 *            'desc' => esc_html__('localized description of item');
3041
+	 *        )
3042
+	 * );
3043
+	 *
3044
+	 * @param array $items see above for format of array
3045
+	 * @return string html string of legend
3046
+	 * @throws DomainException
3047
+	 */
3048
+	protected function _display_legend(array $items): string
3049
+	{
3050
+		$this->_template_args['items'] = (array) apply_filters(
3051
+			'FHEE__EE_Admin_Page___display_legend__items',
3052
+			$items,
3053
+			$this
3054
+		);
3055
+		/** @var StatusChangeNotice $status_change_notice */
3056
+		$status_change_notice                         = $this->loader->getShared(
3057
+			'EventEspresso\core\domain\services\admin\notices\status_change\StatusChangeNotice'
3058
+		);
3059
+		$this->_template_args['status_change_notice'] = $status_change_notice->display(
3060
+			'__admin-legend',
3061
+			$this->page_slug
3062
+		);
3063
+		return EEH_Template::display_template(
3064
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3065
+			$this->_template_args,
3066
+			true
3067
+		);
3068
+	}
3069
+
3070
+
3071
+	/**
3072
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3073
+	 * The returned json object is created from an array in the following format:
3074
+	 * array(
3075
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3076
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3077
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3078
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3079
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3080
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3081
+	 *  that might be included in here)
3082
+	 * )
3083
+	 * The json object is populated by whatever is set in the $_template_args property.
3084
+	 *
3085
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3086
+	 *                                 instead of displayed.
3087
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3088
+	 * @return void
3089
+	 * @throws EE_Error
3090
+	 * @throws InvalidArgumentException
3091
+	 * @throws InvalidDataTypeException
3092
+	 * @throws InvalidInterfaceException
3093
+	 */
3094
+	protected function _return_json(bool $sticky_notices = false, array $notices_arguments = [])
3095
+	{
3096
+		// make sure any EE_Error notices have been handled.
3097
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3098
+		$data = $this->_template_args['data'] ?? [];
3099
+		unset($this->_template_args['data']);
3100
+		$json = [
3101
+			'error'     => $this->_template_args['error'] ?? false,
3102
+			'success'   => $this->_template_args['success'] ?? false,
3103
+			'errors'    => $this->_template_args['errors'] ?? false,
3104
+			'attention' => $this->_template_args['attention'] ?? false,
3105
+			'notices'   => EE_Error::get_notices(),
3106
+			'content'   => $this->_template_args['admin_page_content'] ?? '',
3107
+			'data'      => array_merge($data, ['template_args' => $this->_template_args]),
3108
+			'isEEajax'  => true,
3109
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3110
+		];
3111
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3112
+		if (null === error_get_last() || ! headers_sent()) {
3113
+			header('Content-Type: application/json; charset=UTF-8');
3114
+		}
3115
+		echo wp_json_encode($json);
3116
+		exit();
3117
+	}
3118
+
3119
+
3120
+	/**
3121
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3122
+	 *
3123
+	 * @return void
3124
+	 * @throws EE_Error
3125
+	 * @throws InvalidArgumentException
3126
+	 * @throws InvalidDataTypeException
3127
+	 * @throws InvalidInterfaceException
3128
+	 */
3129
+	public function return_json()
3130
+	{
3131
+		if ($this->request->isAjax()) {
3132
+			$this->_return_json();
3133
+		} else {
3134
+			throw new EE_Error(
3135
+				sprintf(
3136
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3137
+					__FUNCTION__
3138
+				)
3139
+			);
3140
+		}
3141
+	}
3142
+
3143
+
3144
+	/**
3145
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3146
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3147
+	 *
3148
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3149
+	 * @deprecated  5.0.8.p
3150
+	 */
3151
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3152
+	{
3153
+		$this->_hook_obj = $hook_obj;
3154
+	}
3155
+
3156
+
3157
+	/**
3158
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3159
+	 *
3160
+	 * @param bool $about whether to use the special about page wrapper or default.
3161
+	 * @return void
3162
+	 * @throws DomainException
3163
+	 * @throws EE_Error
3164
+	 * @throws InvalidArgumentException
3165
+	 * @throws InvalidDataTypeException
3166
+	 * @throws InvalidInterfaceException
3167
+	 */
3168
+	public function admin_page_wrapper(bool $about = false)
3169
+	{
3170
+		$this->_template_args['nav_tabs']         = $this->_get_main_nav_tabs();
3171
+		$this->_template_args['admin_page_title'] = $this->_admin_page_title;
3172
+
3173
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3174
+			"FHEE_before_admin_page_content$this->_current_page$this->_current_view",
3175
+			$this->_template_args['before_admin_page_content'] ?? ''
3176
+		);
3177
+
3178
+		$this->_template_args['after_admin_page_content'] = apply_filters(
3179
+			"FHEE_after_admin_page_content$this->_current_page$this->_current_view",
3180
+			$this->_template_args['after_admin_page_content'] ?? ''
3181
+		);
3182
+		$this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3183
+
3184
+		if ($this->request->isAjax()) {
3185
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3186
+			// $template_path,
3187
+				EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3188
+				$this->_template_args,
3189
+				true
3190
+			);
3191
+			$this->_return_json();
3192
+		}
3193
+		// load settings page wrapper template
3194
+		$template_path = $about
3195
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3196
+			: EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3197
+
3198
+		EEH_Template::display_template($template_path, $this->_template_args);
3199
+	}
3200
+
3201
+
3202
+	/**
3203
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3204
+	 *
3205
+	 * @return string html
3206
+	 * @throws EE_Error
3207
+	 */
3208
+	protected function _get_main_nav_tabs(): string
3209
+	{
3210
+		// let's generate the html using the EEH_Tabbed_Content helper.
3211
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3212
+		// (rather than setting in the page_routes array)
3213
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs, $this->page_slug);
3214
+	}
3215
+
3216
+
3217
+	/**
3218
+	 *        sort nav tabs
3219
+	 *
3220
+	 * @param array $a
3221
+	 * @param array $b
3222
+	 * @return int
3223
+	 */
3224
+	private function _sort_nav_tabs(array $a, array $b): int
3225
+	{
3226
+		if ($a['order'] === $b['order']) {
3227
+			return 0;
3228
+		}
3229
+		return ($a['order'] < $b['order']) ? -1 : 1;
3230
+	}
3231
+
3232
+
3233
+	/**
3234
+	 * generates HTML for the forms used on admin pages
3235
+	 *
3236
+	 * @param array  $input_vars - array of input field details
3237
+	 * @param string $generator  indicates which generator to use: options are 'string' or 'array'
3238
+	 * @param bool   $id
3239
+	 * @return array|string
3240
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3241
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3242
+	 */
3243
+	protected function _generate_admin_form_fields(
3244
+		array $input_vars = [],
3245
+		string $generator = 'string',
3246
+		bool $id = false
3247
+	) {
3248
+		return $generator === 'string'
3249
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3250
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3251
+	}
3252
+
3253
+
3254
+	/**
3255
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3256
+	 *
3257
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3258
+	 *                                   Close" button.
3259
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3260
+	 *                                   'Save', [1] => 'save & close')
3261
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3262
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3263
+	 *                                   default actions by submitting some other value.
3264
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Otherwise it
3265
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3266
+	 *                                   close (normal form handling).
3267
+	 */
3268
+	protected function _set_save_buttons(bool $both = true, array $text = [], array $actions = [], $referrer = null)
3269
+	{
3270
+		$referrer_url  = ! empty($referrer) ? $referrer : $this->request->getServerParam('REQUEST_URI');
3271
+		$button_text   = ! empty($text)
3272
+			? $text
3273
+			: [
3274
+				esc_html__('Save', 'event_espresso'),
3275
+				esc_html__('Save and Close', 'event_espresso'),
3276
+			];
3277
+		$default_names = ['save', 'save_and_close'];
3278
+		$buttons       = '';
3279
+		foreach ($button_text as $key => $button) {
3280
+			$ref     = $default_names[ $key ];
3281
+			$name    = ! empty($actions) ? $actions[ $key ] : $ref;
3282
+			$buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3283
+						. 'value="' . $button . '" name="' . $name . '" '
3284
+						. 'id="' . $this->_current_view . '_' . $ref . '" />';
3285
+			if (! $both) {
3286
+				break;
3287
+			}
3288
+		}
3289
+		// add in a hidden index for the current page (so save and close redirects properly)
3290
+		$buttons .= '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3291
+					. $referrer_url
3292
+					. '" />';
3293
+
3294
+		$this->_template_args['save_buttons'] = $buttons;
3295
+	}
3296
+
3297
+
3298
+	/**
3299
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3300
+	 *
3301
+	 * @param string $route
3302
+	 * @param array  $additional_hidden_fields
3303
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3304
+	 * @since 4.6.0
3305
+	 */
3306
+	public function set_add_edit_form_tags(string $route = '', array $additional_hidden_fields = [])
3307
+	{
3308
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3309
+	}
3310
+
3311
+
3312
+	/**
3313
+	 * set form open and close tags on add/edit pages.
3314
+	 *
3315
+	 * @param string $route                    the route you want the form to direct to
3316
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3317
+	 * @return void
3318
+	 */
3319
+	protected function _set_add_edit_form_tags(string $route = '', array $additional_hidden_fields = [])
3320
+	{
3321
+		if (empty($route)) {
3322
+			$user_msg = esc_html__(
3323
+				'An error occurred. No action was set for this page\'s form.',
3324
+				'event_espresso'
3325
+			);
3326
+			$dev_msg  = $user_msg . "\n"
3327
+						. sprintf(
3328
+							esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3329
+							__FUNCTION__,
3330
+							__CLASS__
3331
+						);
3332
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3333
+		}
3334
+		// open form
3335
+		$action                                            = $this->_admin_base_url;
3336
+		$this->_template_args['before_admin_page_content'] = "
3337 3337
             <form name='form' method='post' action='$action' id='{$route}_event_form' class='ee-admin-page-form' >
3338 3338
             ";
3339
-        // add nonce
3340
-        $nonce                                             =
3341
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3342
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3343
-        // add REQUIRED form action
3344
-        $hidden_fields = [
3345
-            'action' => ['type' => 'hidden', 'value' => $route],
3346
-        ];
3347
-        // merge arrays
3348
-        $hidden_fields = is_array($additional_hidden_fields)
3349
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3350
-            : $hidden_fields;
3351
-        // generate form fields
3352
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3353
-        // add fields to form
3354
-        foreach ((array) $form_fields as $form_field) {
3355
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3356
-        }
3357
-        // close form
3358
-        $this->_template_args['after_admin_page_content'] = '</form>';
3359
-    }
3360
-
3361
-
3362
-    /**
3363
-     * Public Wrapper for _redirect_after_action() method since its
3364
-     * discovered it would be useful for external code to have access.
3365
-     *
3366
-     * @param bool|int $success
3367
-     * @param string   $what
3368
-     * @param string   $action_desc
3369
-     * @param array    $query_args
3370
-     * @param bool     $override_overwrite
3371
-     * @throws EE_Error
3372
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3373
-     * @since 4.5.0
3374
-     */
3375
-    public function redirect_after_action(
3376
-        $success = false,
3377
-        string $what = 'item',
3378
-        string $action_desc = 'processed',
3379
-        array $query_args = [],
3380
-        bool $override_overwrite = false
3381
-    ) {
3382
-        $this->_redirect_after_action(
3383
-            $success,
3384
-            $what,
3385
-            $action_desc,
3386
-            $query_args,
3387
-            $override_overwrite
3388
-        );
3389
-    }
3390
-
3391
-
3392
-    /**
3393
-     * Helper method for merging existing request data with the returned redirect url.
3394
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3395
-     * filters are still applied.
3396
-     *
3397
-     * @param array $new_route_data
3398
-     * @return array
3399
-     */
3400
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data): array
3401
-    {
3402
-        foreach ($this->request->requestParams() as $ref => $value) {
3403
-            // unset nonces
3404
-            if (strpos($ref, 'nonce') !== false) {
3405
-                $this->request->unSetRequestParam($ref);
3406
-                continue;
3407
-            }
3408
-            // urlencode values.
3409
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3410
-            $this->request->setRequestParam($ref, $value);
3411
-        }
3412
-        return array_merge($this->request->requestParams(), $new_route_data);
3413
-    }
3414
-
3415
-
3416
-    /**
3417
-     * @param int|float|string $success            - whether success was for two or more records, or just one, or none
3418
-     * @param string           $what               - what the action was performed on
3419
-     * @param string           $action_desc        - what was done ie: updated, deleted, etc
3420
-     * @param array            $query_args         - an array of query_args to be added to the URL to redirect to
3421
-     * @param BOOL             $override_overwrite - by default all EE_Error::success messages are overwritten,
3422
-     *                                             this allows you to override this so that they show.
3423
-     * @return void
3424
-     * @throws EE_Error
3425
-     * @throws InvalidArgumentException
3426
-     * @throws InvalidDataTypeException
3427
-     * @throws InvalidInterfaceException
3428
-     */
3429
-    protected function _redirect_after_action(
3430
-        $success = 0,
3431
-        string $what = 'item',
3432
-        string $action_desc = 'processed',
3433
-        array $query_args = [],
3434
-        bool $override_overwrite = false
3435
-    ) {
3436
-        $notices = EE_Error::get_notices(false);
3437
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3438
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3439
-            EE_Error::overwrite_success();
3440
-        }
3441
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3442
-            // how many records affected ? more than one record ? or just one ?
3443
-            EE_Error::add_success(
3444
-                sprintf(
3445
-                    esc_html(
3446
-                        _n(
3447
-                            'The "%1$s" has been successfully %2$s.',
3448
-                            'The "%1$s" have been successfully %2$s.',
3449
-                            $success,
3450
-                            'event_espresso'
3451
-                        )
3452
-                    ),
3453
-                    $what,
3454
-                    $action_desc
3455
-                ),
3456
-                __FILE__,
3457
-                __FUNCTION__,
3458
-                __LINE__
3459
-            );
3460
-        }
3461
-        // check that $query_args isn't something crazy
3462
-        $query_args = is_array($query_args) ? $query_args : [];
3463
-        /**
3464
-         * Allow injecting actions before the query_args are modified for possible different
3465
-         * redirections on save and close actions
3466
-         *
3467
-         * @param array $query_args       The original query_args array coming into the
3468
-         *                                method.
3469
-         * @since 4.2.0
3470
-         */
3471
-        do_action(
3472
-            "AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_$this->_req_action",
3473
-            $query_args
3474
-        );
3475
-        // set redirect url.
3476
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3477
-        // otherwise we go with whatever is set as the _admin_base_url
3478
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3479
-        // calculate where we're going (if we have a "save and close" button pushed)
3480
-        if (
3481
-            $this->request->requestParamIsSet('save_and_close')
3482
-            && $this->request->requestParamIsSet('save_and_close_referrer')
3483
-        ) {
3484
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3485
-            $parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', DataType::URL));
3486
-            // regenerate query args array from referrer URL
3487
-            parse_str($parsed_url['query'], $query_args);
3488
-            // correct page and action will be in the query args now
3489
-            $redirect_url = admin_url('admin.php');
3490
-        }
3491
-        // merge any default query_args set in _default_route_query_args property
3492
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3493
-            $args_to_merge = [];
3494
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3495
-                // is there a wp_referer array in our _default_route_query_args property?
3496
-                if ($query_param === 'wp_referer') {
3497
-                    $query_value = (array) $query_value;
3498
-                    foreach ($query_value as $reference => $value) {
3499
-                        if (strpos($reference, 'nonce') !== false) {
3500
-                            continue;
3501
-                        }
3502
-                        // finally we will override any arguments in the referer with
3503
-                        // what might be set on the _default_route_query_args array.
3504
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3505
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3506
-                        } else {
3507
-                            $args_to_merge[ $reference ] = urlencode($value);
3508
-                        }
3509
-                    }
3510
-                    continue;
3511
-                }
3512
-                $args_to_merge[ $query_param ] = $query_value;
3513
-            }
3514
-            // now let's merge these arguments but override with what was specifically sent in to the
3515
-            // redirect.
3516
-            $query_args = array_merge($args_to_merge, $query_args);
3517
-        }
3518
-        $this->_process_notices($query_args);
3519
-        // generate redirect url
3520
-        // if redirecting to anything other than the main page, add a nonce
3521
-        if (isset($query_args['action'])) {
3522
-            // manually generate wp_nonce and merge that with the query vars
3523
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3524
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3525
-        }
3526
-        // we're adding some hooks and filters in here for processing any things just before redirects
3527
-        // (example: an admin page has done an insert or update and we want to run something after that).
3528
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3529
-        $redirect_url = apply_filters(
3530
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3531
-            EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3532
-            $query_args
3533
-        );
3534
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3535
-        if ($this->request->isAjax()) {
3536
-            $default_data                    = [
3537
-                'close'        => true,
3538
-                'redirect_url' => $redirect_url,
3539
-                'where'        => 'main',
3540
-                'what'         => 'append',
3541
-            ];
3542
-            $this->_template_args['success'] = $success;
3543
-            $this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3544
-                $default_data,
3545
-                $this->_template_args['data']
3546
-            ) : $default_data;
3547
-            $this->_return_json();
3548
-        }
3549
-        wp_safe_redirect($redirect_url);
3550
-        exit();
3551
-    }
3552
-
3553
-
3554
-    /**
3555
-     * process any notices before redirecting (or returning ajax request)
3556
-     * This method sets the $this->_template_args['notices'] attribute;
3557
-     *
3558
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3559
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3560
-     *                                  page_routes haven't been defined yet.
3561
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3562
-     *                                  still save a transient for the notice.
3563
-     * @return void
3564
-     * @throws EE_Error
3565
-     * @throws InvalidArgumentException
3566
-     * @throws InvalidDataTypeException
3567
-     * @throws InvalidInterfaceException
3568
-     */
3569
-    protected function _process_notices(
3570
-        array $query_args = [],
3571
-        bool $skip_route_verify = false,
3572
-        bool $sticky_notices = true
3573
-    ) {
3574
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3575
-        if ($this->request->isAjax()) {
3576
-            $notices = EE_Error::get_notices(false);
3577
-            if (empty($this->_template_args['success'])) {
3578
-                $this->_template_args['success'] = $notices['success'] ?? false;
3579
-            }
3580
-            if (empty($this->_template_args['errors'])) {
3581
-                $this->_template_args['errors'] = $notices['errors'] ?? false;
3582
-            }
3583
-            if (empty($this->_template_args['attention'])) {
3584
-                $this->_template_args['attention'] = $notices['attention'] ?? false;
3585
-            }
3586
-        }
3587
-        $this->_template_args['notices'] = EE_Error::get_notices();
3588
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3589
-        if (! $this->request->isAjax() || $sticky_notices) {
3590
-            $route = $query_args['action'] ?? 'default';
3591
-            $this->_add_transient(
3592
-                $route,
3593
-                (array) $this->_template_args['notices'],
3594
-                true,
3595
-                $skip_route_verify
3596
-            );
3597
-        }
3598
-    }
3599
-
3600
-
3601
-    /**
3602
-     * get_action_link_or_button
3603
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3604
-     *
3605
-     * @param string $action        use this to indicate which action the url is generated with.
3606
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3607
-     *                              property.
3608
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3609
-     * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3610
-     * @param string $base_url      If this is not provided
3611
-     *                              the _admin_base_url will be used as the default for the button base_url.
3612
-     *                              Otherwise this value will be used.
3613
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3614
-     * @return string
3615
-     * @throws InvalidArgumentException
3616
-     * @throws InvalidInterfaceException
3617
-     * @throws InvalidDataTypeException
3618
-     * @throws EE_Error
3619
-     */
3620
-    public function get_action_link_or_button(
3621
-        string $action,
3622
-        string $type = 'add',
3623
-        array $extra_request = [],
3624
-        string $class = 'button button--primary',
3625
-        string $base_url = '',
3626
-        bool $exclude_nonce = false
3627
-    ): string {
3628
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3629
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3630
-            throw new EE_Error(
3631
-                sprintf(
3632
-                    esc_html__(
3633
-                        'There is no page route for given action for the button.  This action was given: %s',
3634
-                        'event_espresso'
3635
-                    ),
3636
-                    $action
3637
-                )
3638
-            );
3639
-        }
3640
-        if (! isset($this->_labels['buttons'][ $type ])) {
3641
-            throw new EE_Error(
3642
-                sprintf(
3643
-                    esc_html__(
3644
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3645
-                        'event_espresso'
3646
-                    ),
3647
-                    $type
3648
-                )
3649
-            );
3650
-        }
3651
-        // finally check user access for this button.
3652
-        $has_access = $this->check_user_access($action, true);
3653
-        if (! $has_access) {
3654
-            return '';
3655
-        }
3656
-        $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3657
-        $query_args = [
3658
-            'action' => $action,
3659
-        ];
3660
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3661
-        if (! empty($extra_request)) {
3662
-            $query_args = array_merge($extra_request, $query_args);
3663
-        }
3664
-        $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3665
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3666
-    }
3667
-
3668
-
3669
-    /**
3670
-     * _per_page_screen_option
3671
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3672
-     *
3673
-     * @return void
3674
-     * @throws InvalidArgumentException
3675
-     * @throws InvalidInterfaceException
3676
-     * @throws InvalidDataTypeException
3677
-     */
3678
-    protected function _per_page_screen_option()
3679
-    {
3680
-        $option = 'per_page';
3681
-        $args   = [
3682
-            'label'   => apply_filters(
3683
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3684
-                $this->_admin_page_title,
3685
-                $this
3686
-            ),
3687
-            'default' => (int) apply_filters(
3688
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3689
-                20
3690
-            ),
3691
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3692
-        ];
3693
-        // ONLY add the screen option if the user has access to it.
3694
-        if ($this->check_user_access($this->_current_view, true)) {
3695
-            add_screen_option($option, $args);
3696
-        }
3697
-    }
3698
-
3699
-
3700
-    /**
3701
-     * set_per_page_screen_option
3702
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3703
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3704
-     * admin_menu.
3705
-     *
3706
-     * @return void
3707
-     */
3708
-    private function _set_per_page_screen_options()
3709
-    {
3710
-        if ($this->request->requestParamIsSet('wp_screen_options')) {
3711
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3712
-            if (! $user = wp_get_current_user()) {
3713
-                return;
3714
-            }
3715
-            $option = $this->request->getRequestParam('wp_screen_options[option]', '', DataType::KEY);
3716
-            if (! $option) {
3717
-                return;
3718
-            }
3719
-            $value      = $this->request->getRequestParam('wp_screen_options[value]', 0, DataType::INT);
3720
-            $map_option = $option;
3721
-            $option     = str_replace('-', '_', $option);
3722
-            switch ($map_option) {
3723
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3724
-                    $max_value = apply_filters(
3725
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3726
-                        999,
3727
-                        $this->_current_page,
3728
-                        $this->_current_view
3729
-                    );
3730
-                    if ($value < 1) {
3731
-                        return;
3732
-                    }
3733
-                    $value = min($value, $max_value);
3734
-                    break;
3735
-                default:
3736
-                    $value = apply_filters(
3737
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3738
-                        false,
3739
-                        $option,
3740
-                        $value
3741
-                    );
3742
-                    if (false === $value) {
3743
-                        return;
3744
-                    }
3745
-                    break;
3746
-            }
3747
-            update_user_meta($user->ID, $option, $value);
3748
-            wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3749
-            exit;
3750
-        }
3751
-    }
3752
-
3753
-
3754
-    /**
3755
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3756
-     *
3757
-     * @param array $data array that will be assigned to template args.
3758
-     */
3759
-    public function set_template_args(array $data)
3760
-    {
3761
-        $this->_template_args = array_merge($this->_template_args, $data);
3762
-    }
3763
-
3764
-
3765
-    public function setAdminPageTitle(string $title)
3766
-    {
3767
-        $this->_admin_page_title = sanitize_text_field($title);
3768
-    }
3769
-
3770
-
3771
-    /**
3772
-     * This makes available the WP transient system for temporarily moving data between routes
3773
-     *
3774
-     * @param string $route             the route that should receive the transient
3775
-     * @param array  $data              the data that gets sent
3776
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise it's just a
3777
-     *                                  normal route transient.
3778
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3779
-     *                                  when we are adding a transient before page_routes have been defined.
3780
-     * @return void
3781
-     * @throws EE_Error
3782
-     */
3783
-    protected function _add_transient(
3784
-        string $route,
3785
-        array $data,
3786
-        bool $notices = false,
3787
-        bool $skip_route_verify = false
3788
-    ) {
3789
-        $user_id = get_current_user_id();
3790
-        if (! $skip_route_verify) {
3791
-            $this->_verify_route($route);
3792
-        }
3793
-        // now let's set the string for what kind of transient we're setting
3794
-        $transient = $notices ? "ee_rte_n_tx_{$route}_$user_id" : "rte_tx_{$route}_$user_id";
3795
-        $data      = $notices ? ['notices' => $data] : $data;
3796
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3797
-        $existing = is_multisite() && is_network_admin()
3798
-            ? get_site_transient($transient)
3799
-            : get_transient($transient);
3800
-        if ($existing) {
3801
-            $data = array_merge($data, (array) $existing);
3802
-        }
3803
-        if (is_multisite() && is_network_admin()) {
3804
-            set_site_transient($transient, $data, 8);
3805
-        } else {
3806
-            set_transient($transient, $data, 8);
3807
-        }
3808
-    }
3809
-
3810
-
3811
-    /**
3812
-     * this retrieves the temporary transient that has been set for moving data between routes.
3813
-     *
3814
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3815
-     * @param string $route
3816
-     * @return mixed data
3817
-     */
3818
-    protected function _get_transient(bool $notices = false, string $route = '')
3819
-    {
3820
-        $user_id   = get_current_user_id();
3821
-        $route     = ! $route ? $this->_req_action : $route;
3822
-        $transient = $notices
3823
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3824
-            : 'rte_tx_' . $route . '_' . $user_id;
3825
-        $data      = is_multisite() && is_network_admin()
3826
-            ? get_site_transient($transient)
3827
-            : get_transient($transient);
3828
-        // delete transient after retrieval (just in case it hasn't expired);
3829
-        if (is_multisite() && is_network_admin()) {
3830
-            delete_site_transient($transient);
3831
-        } else {
3832
-            delete_transient($transient);
3833
-        }
3834
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3835
-    }
3836
-
3837
-
3838
-    /**
3839
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3840
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3841
-     * default route callback on the EE_Admin page you want it run.)
3842
-     *
3843
-     * @return void
3844
-     */
3845
-    protected function _transient_garbage_collection()
3846
-    {
3847
-        global $wpdb;
3848
-        // retrieve all existing transients
3849
-        $query =
3850
-            "SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3851
-        if ($results = $wpdb->get_results($query)) {
3852
-            foreach ($results as $result) {
3853
-                $transient = str_replace('_transient_', '', $result->option_name);
3854
-                get_transient($transient);
3855
-                if (is_multisite() && is_network_admin()) {
3856
-                    get_site_transient($transient);
3857
-                }
3858
-            }
3859
-        }
3860
-    }
3861
-
3862
-
3863
-    /**
3864
-     * get_view
3865
-     *
3866
-     * @return string content of _view property
3867
-     */
3868
-    public function get_view(): string
3869
-    {
3870
-        return $this->_view;
3871
-    }
3872
-
3873
-
3874
-    /**
3875
-     * getter for the protected $_views property
3876
-     *
3877
-     * @return array
3878
-     */
3879
-    public function get_views(): array
3880
-    {
3881
-        return $this->_views;
3882
-    }
3883
-
3884
-
3885
-    /**
3886
-     * @param array $views
3887
-     * @return void
3888
-     * @since 5.0.13.p
3889
-     */
3890
-    public function updateViews(array $views)
3891
-    {
3892
-        $this->_views = array_merge($this->_views, $views);
3893
-    }
3894
-
3895
-
3896
-    /**
3897
-    /**
3898
-     * get_current_page
3899
-     *
3900
-     * @return string _current_page property value
3901
-     */
3902
-    public function get_current_page(): string
3903
-    {
3904
-        return $this->_current_page;
3905
-    }
3906
-
3907
-
3908
-    /**
3909
-     * get_current_view
3910
-     *
3911
-     * @return string _current_view property value
3912
-     */
3913
-    public function get_current_view(): string
3914
-    {
3915
-        return $this->_current_view;
3916
-    }
3917
-
3918
-
3919
-    /**
3920
-     * get_current_screen
3921
-     *
3922
-     * @return object The current WP_Screen object
3923
-     */
3924
-    public function get_current_screen()
3925
-    {
3926
-        return $this->_current_screen;
3927
-    }
3928
-
3929
-
3930
-    /**
3931
-     * get_current_page_view_url
3932
-     *
3933
-     * @return string This returns the url for the current_page_view.
3934
-     */
3935
-    public function get_current_page_view_url(): string
3936
-    {
3937
-        return $this->_current_page_view_url;
3938
-    }
3939
-
3940
-
3941
-    /**
3942
-     * just returns the Request
3943
-     *
3944
-     * @return RequestInterface
3945
-     */
3946
-    public function get_request(): ?RequestInterface
3947
-    {
3948
-        return $this->request;
3949
-    }
3950
-
3951
-
3952
-    /**
3953
-     * just returns the _req_data property
3954
-     *
3955
-     * @return array
3956
-     */
3957
-    public function get_request_data(): array
3958
-    {
3959
-        return $this->request->requestParams();
3960
-    }
3961
-
3962
-
3963
-    /**
3964
-     * returns the _req_data protected property
3965
-     *
3966
-     * @return string
3967
-     */
3968
-    public function get_req_action(): string
3969
-    {
3970
-        return $this->_req_action;
3971
-    }
3972
-
3973
-
3974
-    /**
3975
-     * @return bool  value of $_is_caf property
3976
-     */
3977
-    public function is_caf(): bool
3978
-    {
3979
-        return $this->_is_caf;
3980
-    }
3981
-
3982
-
3983
-    /**
3984
-     * @return array
3985
-     */
3986
-    public function default_espresso_metaboxes(): array
3987
-    {
3988
-        return $this->_default_espresso_metaboxes;
3989
-    }
3990
-
3991
-
3992
-    /**
3993
-     * @return string
3994
-     */
3995
-    public function admin_base_url(): string
3996
-    {
3997
-        return $this->_admin_base_url;
3998
-    }
3999
-
4000
-
4001
-    /**
4002
-     * @return string
4003
-     */
4004
-    public function wp_page_slug(): string
4005
-    {
4006
-        return $this->_wp_page_slug;
4007
-    }
4008
-
4009
-
4010
-    /**
4011
-     * updates  espresso configuration settings
4012
-     *
4013
-     * @param string                   $tab
4014
-     * @param EE_Config_Base|EE_Config $config
4015
-     * @param string                   $file file where error occurred
4016
-     * @param string                   $func function  where error occurred
4017
-     * @param string                   $line line no where error occurred
4018
-     * @return bool
4019
-     */
4020
-    protected function _update_espresso_configuration(
4021
-        string $tab,
4022
-        $config,
4023
-        string $file = '',
4024
-        string $func = '',
4025
-        string $line = ''
4026
-    ): bool {
4027
-        // remove any options that are NOT going to be saved with the config settings.
4028
-        if (isset($config->core->ee_ueip_optin)) {
4029
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
4030
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4031
-            update_option('ee_ueip_has_notified', true);
4032
-        }
4033
-        // and save it (note we're also doing the network save here)
4034
-        $net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
4035
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4036
-        if ($config_saved && $net_saved) {
4037
-            EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4038
-            return true;
4039
-        }
4040
-        EE_Error::add_error(
4041
-            sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab),
4042
-            $file,
4043
-            $func,
4044
-            $line
4045
-        );
4046
-        return false;
4047
-    }
4048
-
4049
-
4050
-    /**
4051
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4052
-     *
4053
-     * @return array
4054
-     */
4055
-    public function get_yes_no_values(): array
4056
-    {
4057
-        return $this->_yes_no_values;
4058
-    }
4059
-
4060
-
4061
-    /**
4062
-     * @return string
4063
-     * @throws ReflectionException
4064
-     * @since 5.0.0.p
4065
-     */
4066
-    protected function _get_dir(): string
4067
-    {
4068
-        $reflector = new ReflectionClass($this->class_name);
4069
-        return dirname($reflector->getFileName());
4070
-    }
4071
-
4072
-
4073
-    /**
4074
-     * A helper for getting a "next link".
4075
-     *
4076
-     * @param string $url   The url to link to
4077
-     * @param string $class The class to use.
4078
-     * @return string
4079
-     */
4080
-    protected function _next_link(string $url, string $class = 'dashicons dashicons-arrow-right'): string
4081
-    {
4082
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4083
-    }
4084
-
4085
-
4086
-    /**
4087
-     * A helper for getting a "previous link".
4088
-     *
4089
-     * @param string $url   The url to link to
4090
-     * @param string $class The class to use.
4091
-     * @return string
4092
-     */
4093
-    protected function _previous_link(string $url, string $class = 'dashicons dashicons-arrow-left'): string
4094
-    {
4095
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4096
-    }
4097
-
4098
-
4099
-
4100
-
4101
-
4102
-
4103
-
4104
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4105
-
4106
-
4107
-    /**
4108
-     * This processes a request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4109
-     * 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
4110
-     * _req_data array.
4111
-     *
4112
-     * @return bool success/fail
4113
-     * @throws EE_Error
4114
-     * @throws InvalidArgumentException
4115
-     * @throws ReflectionException
4116
-     * @throws InvalidDataTypeException
4117
-     * @throws InvalidInterfaceException
4118
-     */
4119
-    protected function _process_resend_registration(): bool
4120
-    {
4121
-        $this->_template_args['success'] = EED_Messages::process_resend($this->request->requestParams());
4122
-        do_action(
4123
-            'AHEE__EE_Admin_Page___process_resend_registration',
4124
-            $this->_template_args['success'],
4125
-            $this->request->requestParams()
4126
-        );
4127
-        return $this->_template_args['success'];
4128
-    }
4129
-
4130
-
4131
-    /**
4132
-     * This automatically processes any payment message notifications when manual payment has been applied.
4133
-     *
4134
-     * @param EE_Payment $payment
4135
-     * @return bool success/fail
4136
-     */
4137
-    protected function _process_payment_notification(EE_Payment $payment): bool
4138
-    {
4139
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4140
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4141
-        $this->_template_args['success'] = apply_filters(
4142
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4143
-            false,
4144
-            $payment
4145
-        );
4146
-        return $this->_template_args['success'];
4147
-    }
4148
-
4149
-
4150
-    /**
4151
-     * @param EEM_Base      $entity_model
4152
-     * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4153
-     * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4154
-     * @param string        $delete_column  name of the field that denotes whether entity is trashed
4155
-     * @param callable|null $callback       called after entity is trashed, restored, or deleted
4156
-     * @return int|float
4157
-     * @throws EE_Error
4158
-     */
4159
-    protected function trashRestoreDeleteEntities(
4160
-        EEM_Base $entity_model,
4161
-        string $entity_PK_name,
4162
-        string $action = EE_Admin_List_Table::ACTION_DELETE,
4163
-        string $delete_column = '',
4164
-        ?callable $callback = null
4165
-    ) {
4166
-        $entity_PK      = $entity_model->get_primary_key_field();
4167
-        $entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4168
-        $entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4169
-        // grab ID if deleting a single entity
4170
-        if ($this->request->requestParamIsSet($entity_PK_name)) {
4171
-            $ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4172
-            return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4173
-        }
4174
-        // or grab checkbox array if bulk deleting
4175
-        $checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4176
-        if (empty($checkboxes)) {
4177
-            return 0;
4178
-        }
4179
-        $success = 0;
4180
-        $IDs     = array_keys($checkboxes);
4181
-        // cycle thru bulk action checkboxes
4182
-        foreach ($IDs as $ID) {
4183
-            // increment $success
4184
-            if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4185
-                $success++;
4186
-            }
4187
-        }
4188
-        $count = (int) count($checkboxes);
4189
-        // if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4190
-        // otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4191
-        return $success === $count ? $count : $success / $count;
4192
-    }
4193
-
4194
-
4195
-    /**
4196
-     * @param EE_Primary_Key_Field_Base $entity_PK
4197
-     * @return string
4198
-     * @throws EE_Error
4199
-     * @since   4.10.30.p
4200
-     */
4201
-    private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4202
-    {
4203
-        $entity_PK_type = $entity_PK->getSchemaType();
4204
-        switch ($entity_PK_type) {
4205
-            case 'boolean':
4206
-                return DataType::BOOL;
4207
-            case 'integer':
4208
-                return DataType::INT;
4209
-            case 'number':
4210
-                return DataType::FLOAT;
4211
-            case 'string':
4212
-                return DataType::STRING;
4213
-        }
4214
-        throw new RuntimeException(
4215
-            sprintf(
4216
-                esc_html__(
4217
-                    '"%1$s" is an invalid schema type for the %2$s primary key.',
4218
-                    'event_espresso'
4219
-                ),
4220
-                $entity_PK_type,
4221
-                $entity_PK->get_name()
4222
-            )
4223
-        );
4224
-    }
4225
-
4226
-
4227
-    /**
4228
-     * @param EEM_Base      $entity_model
4229
-     * @param int|string    $entity_ID
4230
-     * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4231
-     * @param string        $delete_column name of the field that denotes whether entity is trashed
4232
-     * @param callable|null $callback      called after entity is trashed, restored, or deleted
4233
-     * @return bool
4234
-     */
4235
-    protected function trashRestoreDeleteEntity(
4236
-        EEM_Base $entity_model,
4237
-        $entity_ID,
4238
-        string $action,
4239
-        string $delete_column,
4240
-        ?callable $callback = null
4241
-    ): bool {
4242
-        $entity_ID = absint($entity_ID);
4243
-        if (! $entity_ID) {
4244
-            $this->trashRestoreDeleteError($action, $entity_model);
4245
-        }
4246
-        $result = 0;
4247
-        try {
4248
-            $entity = $entity_model->get_one_by_ID($entity_ID);
4249
-            if (! $entity instanceof EE_Base_Class) {
4250
-                throw new DomainException(
4251
-                    sprintf(
4252
-                        esc_html__(
4253
-                            'Missing or invalid %1$s entity with ID of "%2$s" returned from db.',
4254
-                            'event_espresso'
4255
-                        ),
4256
-                        str_replace('EEM_', '', $entity_model->get_this_model_name()),
4257
-                        $entity_ID
4258
-                    )
4259
-                );
4260
-            }
4261
-            switch ($action) {
4262
-                case EE_Admin_List_Table::ACTION_DELETE:
4263
-                    $result = (bool) $entity->delete_permanently();
4264
-                    break;
4265
-                case EE_Admin_List_Table::ACTION_RESTORE:
4266
-                    $result = $entity->delete_or_restore(false);
4267
-                    break;
4268
-                case EE_Admin_List_Table::ACTION_TRASH:
4269
-                    $result = $entity->delete_or_restore();
4270
-                    break;
4271
-            }
4272
-        } catch (Exception $exception) {
4273
-            $this->trashRestoreDeleteError($action, $entity_model, $exception);
4274
-        }
4275
-        if (is_callable($callback)) {
4276
-            call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4277
-        }
4278
-        return $result;
4279
-    }
4280
-
4281
-
4282
-    /**
4283
-     * @param EEM_Base $entity_model
4284
-     * @param string   $delete_column
4285
-     * @since 4.10.30.p
4286
-     */
4287
-    private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4288
-    {
4289
-        if (empty($delete_column)) {
4290
-            throw new DomainException(
4291
-                sprintf(
4292
-                    esc_html__(
4293
-                        'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4294
-                        'event_espresso'
4295
-                    ),
4296
-                    $entity_model->get_this_model_name()
4297
-                )
4298
-            );
4299
-        }
4300
-        if (! $entity_model->has_field($delete_column)) {
4301
-            throw new DomainException(
4302
-                sprintf(
4303
-                    esc_html__(
4304
-                        'The %1$s field does not exist on the %2$s model.',
4305
-                        'event_espresso'
4306
-                    ),
4307
-                    $delete_column,
4308
-                    $entity_model->get_this_model_name()
4309
-                )
4310
-            );
4311
-        }
4312
-    }
4313
-
4314
-
4315
-    /**
4316
-     * @param EEM_Base       $entity_model
4317
-     * @param Exception|null $exception
4318
-     * @param string         $action
4319
-     * @since 4.10.30.p
4320
-     */
4321
-    private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, Exception $exception = null)
4322
-    {
4323
-        if ($exception instanceof Exception) {
4324
-            throw new RuntimeException(
4325
-                sprintf(
4326
-                    esc_html__(
4327
-                        'Could not %1$s the %2$s because the following error occurred: %3$s',
4328
-                        'event_espresso'
4329
-                    ),
4330
-                    $action,
4331
-                    $entity_model->get_this_model_name(),
4332
-                    $exception->getMessage()
4333
-                )
4334
-            );
4335
-        }
4336
-        throw new RuntimeException(
4337
-            sprintf(
4338
-                esc_html__(
4339
-                    'Could not %1$s the %2$s because an invalid ID was received.',
4340
-                    'event_espresso'
4341
-                ),
4342
-                $action,
4343
-                $entity_model->get_this_model_name()
4344
-            )
4345
-        );
4346
-    }
3339
+		// add nonce
3340
+		$nonce                                             =
3341
+			wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3342
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3343
+		// add REQUIRED form action
3344
+		$hidden_fields = [
3345
+			'action' => ['type' => 'hidden', 'value' => $route],
3346
+		];
3347
+		// merge arrays
3348
+		$hidden_fields = is_array($additional_hidden_fields)
3349
+			? array_merge($hidden_fields, $additional_hidden_fields)
3350
+			: $hidden_fields;
3351
+		// generate form fields
3352
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3353
+		// add fields to form
3354
+		foreach ((array) $form_fields as $form_field) {
3355
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3356
+		}
3357
+		// close form
3358
+		$this->_template_args['after_admin_page_content'] = '</form>';
3359
+	}
3360
+
3361
+
3362
+	/**
3363
+	 * Public Wrapper for _redirect_after_action() method since its
3364
+	 * discovered it would be useful for external code to have access.
3365
+	 *
3366
+	 * @param bool|int $success
3367
+	 * @param string   $what
3368
+	 * @param string   $action_desc
3369
+	 * @param array    $query_args
3370
+	 * @param bool     $override_overwrite
3371
+	 * @throws EE_Error
3372
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3373
+	 * @since 4.5.0
3374
+	 */
3375
+	public function redirect_after_action(
3376
+		$success = false,
3377
+		string $what = 'item',
3378
+		string $action_desc = 'processed',
3379
+		array $query_args = [],
3380
+		bool $override_overwrite = false
3381
+	) {
3382
+		$this->_redirect_after_action(
3383
+			$success,
3384
+			$what,
3385
+			$action_desc,
3386
+			$query_args,
3387
+			$override_overwrite
3388
+		);
3389
+	}
3390
+
3391
+
3392
+	/**
3393
+	 * Helper method for merging existing request data with the returned redirect url.
3394
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3395
+	 * filters are still applied.
3396
+	 *
3397
+	 * @param array $new_route_data
3398
+	 * @return array
3399
+	 */
3400
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data): array
3401
+	{
3402
+		foreach ($this->request->requestParams() as $ref => $value) {
3403
+			// unset nonces
3404
+			if (strpos($ref, 'nonce') !== false) {
3405
+				$this->request->unSetRequestParam($ref);
3406
+				continue;
3407
+			}
3408
+			// urlencode values.
3409
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3410
+			$this->request->setRequestParam($ref, $value);
3411
+		}
3412
+		return array_merge($this->request->requestParams(), $new_route_data);
3413
+	}
3414
+
3415
+
3416
+	/**
3417
+	 * @param int|float|string $success            - whether success was for two or more records, or just one, or none
3418
+	 * @param string           $what               - what the action was performed on
3419
+	 * @param string           $action_desc        - what was done ie: updated, deleted, etc
3420
+	 * @param array            $query_args         - an array of query_args to be added to the URL to redirect to
3421
+	 * @param BOOL             $override_overwrite - by default all EE_Error::success messages are overwritten,
3422
+	 *                                             this allows you to override this so that they show.
3423
+	 * @return void
3424
+	 * @throws EE_Error
3425
+	 * @throws InvalidArgumentException
3426
+	 * @throws InvalidDataTypeException
3427
+	 * @throws InvalidInterfaceException
3428
+	 */
3429
+	protected function _redirect_after_action(
3430
+		$success = 0,
3431
+		string $what = 'item',
3432
+		string $action_desc = 'processed',
3433
+		array $query_args = [],
3434
+		bool $override_overwrite = false
3435
+	) {
3436
+		$notices = EE_Error::get_notices(false);
3437
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3438
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3439
+			EE_Error::overwrite_success();
3440
+		}
3441
+		if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3442
+			// how many records affected ? more than one record ? or just one ?
3443
+			EE_Error::add_success(
3444
+				sprintf(
3445
+					esc_html(
3446
+						_n(
3447
+							'The "%1$s" has been successfully %2$s.',
3448
+							'The "%1$s" have been successfully %2$s.',
3449
+							$success,
3450
+							'event_espresso'
3451
+						)
3452
+					),
3453
+					$what,
3454
+					$action_desc
3455
+				),
3456
+				__FILE__,
3457
+				__FUNCTION__,
3458
+				__LINE__
3459
+			);
3460
+		}
3461
+		// check that $query_args isn't something crazy
3462
+		$query_args = is_array($query_args) ? $query_args : [];
3463
+		/**
3464
+		 * Allow injecting actions before the query_args are modified for possible different
3465
+		 * redirections on save and close actions
3466
+		 *
3467
+		 * @param array $query_args       The original query_args array coming into the
3468
+		 *                                method.
3469
+		 * @since 4.2.0
3470
+		 */
3471
+		do_action(
3472
+			"AHEE__{$this->class_name}___redirect_after_action__before_redirect_modification_$this->_req_action",
3473
+			$query_args
3474
+		);
3475
+		// set redirect url.
3476
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3477
+		// otherwise we go with whatever is set as the _admin_base_url
3478
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3479
+		// calculate where we're going (if we have a "save and close" button pushed)
3480
+		if (
3481
+			$this->request->requestParamIsSet('save_and_close')
3482
+			&& $this->request->requestParamIsSet('save_and_close_referrer')
3483
+		) {
3484
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3485
+			$parsed_url = parse_url($this->request->getRequestParam('save_and_close_referrer', '', DataType::URL));
3486
+			// regenerate query args array from referrer URL
3487
+			parse_str($parsed_url['query'], $query_args);
3488
+			// correct page and action will be in the query args now
3489
+			$redirect_url = admin_url('admin.php');
3490
+		}
3491
+		// merge any default query_args set in _default_route_query_args property
3492
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3493
+			$args_to_merge = [];
3494
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3495
+				// is there a wp_referer array in our _default_route_query_args property?
3496
+				if ($query_param === 'wp_referer') {
3497
+					$query_value = (array) $query_value;
3498
+					foreach ($query_value as $reference => $value) {
3499
+						if (strpos($reference, 'nonce') !== false) {
3500
+							continue;
3501
+						}
3502
+						// finally we will override any arguments in the referer with
3503
+						// what might be set on the _default_route_query_args array.
3504
+						if (isset($this->_default_route_query_args[ $reference ])) {
3505
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3506
+						} else {
3507
+							$args_to_merge[ $reference ] = urlencode($value);
3508
+						}
3509
+					}
3510
+					continue;
3511
+				}
3512
+				$args_to_merge[ $query_param ] = $query_value;
3513
+			}
3514
+			// now let's merge these arguments but override with what was specifically sent in to the
3515
+			// redirect.
3516
+			$query_args = array_merge($args_to_merge, $query_args);
3517
+		}
3518
+		$this->_process_notices($query_args);
3519
+		// generate redirect url
3520
+		// if redirecting to anything other than the main page, add a nonce
3521
+		if (isset($query_args['action'])) {
3522
+			// manually generate wp_nonce and merge that with the query vars
3523
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3524
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3525
+		}
3526
+		// we're adding some hooks and filters in here for processing any things just before redirects
3527
+		// (example: an admin page has done an insert or update and we want to run something after that).
3528
+		do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3529
+		$redirect_url = apply_filters(
3530
+			'FHEE_redirect_' . $this->class_name . $this->_req_action,
3531
+			EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3532
+			$query_args
3533
+		);
3534
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3535
+		if ($this->request->isAjax()) {
3536
+			$default_data                    = [
3537
+				'close'        => true,
3538
+				'redirect_url' => $redirect_url,
3539
+				'where'        => 'main',
3540
+				'what'         => 'append',
3541
+			];
3542
+			$this->_template_args['success'] = $success;
3543
+			$this->_template_args['data']    = ! empty($this->_template_args['data']) ? array_merge(
3544
+				$default_data,
3545
+				$this->_template_args['data']
3546
+			) : $default_data;
3547
+			$this->_return_json();
3548
+		}
3549
+		wp_safe_redirect($redirect_url);
3550
+		exit();
3551
+	}
3552
+
3553
+
3554
+	/**
3555
+	 * process any notices before redirecting (or returning ajax request)
3556
+	 * This method sets the $this->_template_args['notices'] attribute;
3557
+	 *
3558
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3559
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3560
+	 *                                  page_routes haven't been defined yet.
3561
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3562
+	 *                                  still save a transient for the notice.
3563
+	 * @return void
3564
+	 * @throws EE_Error
3565
+	 * @throws InvalidArgumentException
3566
+	 * @throws InvalidDataTypeException
3567
+	 * @throws InvalidInterfaceException
3568
+	 */
3569
+	protected function _process_notices(
3570
+		array $query_args = [],
3571
+		bool $skip_route_verify = false,
3572
+		bool $sticky_notices = true
3573
+	) {
3574
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3575
+		if ($this->request->isAjax()) {
3576
+			$notices = EE_Error::get_notices(false);
3577
+			if (empty($this->_template_args['success'])) {
3578
+				$this->_template_args['success'] = $notices['success'] ?? false;
3579
+			}
3580
+			if (empty($this->_template_args['errors'])) {
3581
+				$this->_template_args['errors'] = $notices['errors'] ?? false;
3582
+			}
3583
+			if (empty($this->_template_args['attention'])) {
3584
+				$this->_template_args['attention'] = $notices['attention'] ?? false;
3585
+			}
3586
+		}
3587
+		$this->_template_args['notices'] = EE_Error::get_notices();
3588
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3589
+		if (! $this->request->isAjax() || $sticky_notices) {
3590
+			$route = $query_args['action'] ?? 'default';
3591
+			$this->_add_transient(
3592
+				$route,
3593
+				(array) $this->_template_args['notices'],
3594
+				true,
3595
+				$skip_route_verify
3596
+			);
3597
+		}
3598
+	}
3599
+
3600
+
3601
+	/**
3602
+	 * get_action_link_or_button
3603
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3604
+	 *
3605
+	 * @param string $action        use this to indicate which action the url is generated with.
3606
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3607
+	 *                              property.
3608
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3609
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button--primary'
3610
+	 * @param string $base_url      If this is not provided
3611
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3612
+	 *                              Otherwise this value will be used.
3613
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3614
+	 * @return string
3615
+	 * @throws InvalidArgumentException
3616
+	 * @throws InvalidInterfaceException
3617
+	 * @throws InvalidDataTypeException
3618
+	 * @throws EE_Error
3619
+	 */
3620
+	public function get_action_link_or_button(
3621
+		string $action,
3622
+		string $type = 'add',
3623
+		array $extra_request = [],
3624
+		string $class = 'button button--primary',
3625
+		string $base_url = '',
3626
+		bool $exclude_nonce = false
3627
+	): string {
3628
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3629
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3630
+			throw new EE_Error(
3631
+				sprintf(
3632
+					esc_html__(
3633
+						'There is no page route for given action for the button.  This action was given: %s',
3634
+						'event_espresso'
3635
+					),
3636
+					$action
3637
+				)
3638
+			);
3639
+		}
3640
+		if (! isset($this->_labels['buttons'][ $type ])) {
3641
+			throw new EE_Error(
3642
+				sprintf(
3643
+					esc_html__(
3644
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3645
+						'event_espresso'
3646
+					),
3647
+					$type
3648
+				)
3649
+			);
3650
+		}
3651
+		// finally check user access for this button.
3652
+		$has_access = $this->check_user_access($action, true);
3653
+		if (! $has_access) {
3654
+			return '';
3655
+		}
3656
+		$_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
3657
+		$query_args = [
3658
+			'action' => $action,
3659
+		];
3660
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3661
+		if (! empty($extra_request)) {
3662
+			$query_args = array_merge($extra_request, $query_args);
3663
+		}
3664
+		$url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3665
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3666
+	}
3667
+
3668
+
3669
+	/**
3670
+	 * _per_page_screen_option
3671
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3672
+	 *
3673
+	 * @return void
3674
+	 * @throws InvalidArgumentException
3675
+	 * @throws InvalidInterfaceException
3676
+	 * @throws InvalidDataTypeException
3677
+	 */
3678
+	protected function _per_page_screen_option()
3679
+	{
3680
+		$option = 'per_page';
3681
+		$args   = [
3682
+			'label'   => apply_filters(
3683
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3684
+				$this->_admin_page_title,
3685
+				$this
3686
+			),
3687
+			'default' => (int) apply_filters(
3688
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3689
+				20
3690
+			),
3691
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3692
+		];
3693
+		// ONLY add the screen option if the user has access to it.
3694
+		if ($this->check_user_access($this->_current_view, true)) {
3695
+			add_screen_option($option, $args);
3696
+		}
3697
+	}
3698
+
3699
+
3700
+	/**
3701
+	 * set_per_page_screen_option
3702
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3703
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3704
+	 * admin_menu.
3705
+	 *
3706
+	 * @return void
3707
+	 */
3708
+	private function _set_per_page_screen_options()
3709
+	{
3710
+		if ($this->request->requestParamIsSet('wp_screen_options')) {
3711
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3712
+			if (! $user = wp_get_current_user()) {
3713
+				return;
3714
+			}
3715
+			$option = $this->request->getRequestParam('wp_screen_options[option]', '', DataType::KEY);
3716
+			if (! $option) {
3717
+				return;
3718
+			}
3719
+			$value      = $this->request->getRequestParam('wp_screen_options[value]', 0, DataType::INT);
3720
+			$map_option = $option;
3721
+			$option     = str_replace('-', '_', $option);
3722
+			switch ($map_option) {
3723
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3724
+					$max_value = apply_filters(
3725
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3726
+						999,
3727
+						$this->_current_page,
3728
+						$this->_current_view
3729
+					);
3730
+					if ($value < 1) {
3731
+						return;
3732
+					}
3733
+					$value = min($value, $max_value);
3734
+					break;
3735
+				default:
3736
+					$value = apply_filters(
3737
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3738
+						false,
3739
+						$option,
3740
+						$value
3741
+					);
3742
+					if (false === $value) {
3743
+						return;
3744
+					}
3745
+					break;
3746
+			}
3747
+			update_user_meta($user->ID, $option, $value);
3748
+			wp_safe_redirect(remove_query_arg(['pagenum', 'apage', 'paged'], wp_get_referer()));
3749
+			exit;
3750
+		}
3751
+	}
3752
+
3753
+
3754
+	/**
3755
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3756
+	 *
3757
+	 * @param array $data array that will be assigned to template args.
3758
+	 */
3759
+	public function set_template_args(array $data)
3760
+	{
3761
+		$this->_template_args = array_merge($this->_template_args, $data);
3762
+	}
3763
+
3764
+
3765
+	public function setAdminPageTitle(string $title)
3766
+	{
3767
+		$this->_admin_page_title = sanitize_text_field($title);
3768
+	}
3769
+
3770
+
3771
+	/**
3772
+	 * This makes available the WP transient system for temporarily moving data between routes
3773
+	 *
3774
+	 * @param string $route             the route that should receive the transient
3775
+	 * @param array  $data              the data that gets sent
3776
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise it's just a
3777
+	 *                                  normal route transient.
3778
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3779
+	 *                                  when we are adding a transient before page_routes have been defined.
3780
+	 * @return void
3781
+	 * @throws EE_Error
3782
+	 */
3783
+	protected function _add_transient(
3784
+		string $route,
3785
+		array $data,
3786
+		bool $notices = false,
3787
+		bool $skip_route_verify = false
3788
+	) {
3789
+		$user_id = get_current_user_id();
3790
+		if (! $skip_route_verify) {
3791
+			$this->_verify_route($route);
3792
+		}
3793
+		// now let's set the string for what kind of transient we're setting
3794
+		$transient = $notices ? "ee_rte_n_tx_{$route}_$user_id" : "rte_tx_{$route}_$user_id";
3795
+		$data      = $notices ? ['notices' => $data] : $data;
3796
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3797
+		$existing = is_multisite() && is_network_admin()
3798
+			? get_site_transient($transient)
3799
+			: get_transient($transient);
3800
+		if ($existing) {
3801
+			$data = array_merge($data, (array) $existing);
3802
+		}
3803
+		if (is_multisite() && is_network_admin()) {
3804
+			set_site_transient($transient, $data, 8);
3805
+		} else {
3806
+			set_transient($transient, $data, 8);
3807
+		}
3808
+	}
3809
+
3810
+
3811
+	/**
3812
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3813
+	 *
3814
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3815
+	 * @param string $route
3816
+	 * @return mixed data
3817
+	 */
3818
+	protected function _get_transient(bool $notices = false, string $route = '')
3819
+	{
3820
+		$user_id   = get_current_user_id();
3821
+		$route     = ! $route ? $this->_req_action : $route;
3822
+		$transient = $notices
3823
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3824
+			: 'rte_tx_' . $route . '_' . $user_id;
3825
+		$data      = is_multisite() && is_network_admin()
3826
+			? get_site_transient($transient)
3827
+			: get_transient($transient);
3828
+		// delete transient after retrieval (just in case it hasn't expired);
3829
+		if (is_multisite() && is_network_admin()) {
3830
+			delete_site_transient($transient);
3831
+		} else {
3832
+			delete_transient($transient);
3833
+		}
3834
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3835
+	}
3836
+
3837
+
3838
+	/**
3839
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3840
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3841
+	 * default route callback on the EE_Admin page you want it run.)
3842
+	 *
3843
+	 * @return void
3844
+	 */
3845
+	protected function _transient_garbage_collection()
3846
+	{
3847
+		global $wpdb;
3848
+		// retrieve all existing transients
3849
+		$query =
3850
+			"SELECT option_name FROM $wpdb->options WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3851
+		if ($results = $wpdb->get_results($query)) {
3852
+			foreach ($results as $result) {
3853
+				$transient = str_replace('_transient_', '', $result->option_name);
3854
+				get_transient($transient);
3855
+				if (is_multisite() && is_network_admin()) {
3856
+					get_site_transient($transient);
3857
+				}
3858
+			}
3859
+		}
3860
+	}
3861
+
3862
+
3863
+	/**
3864
+	 * get_view
3865
+	 *
3866
+	 * @return string content of _view property
3867
+	 */
3868
+	public function get_view(): string
3869
+	{
3870
+		return $this->_view;
3871
+	}
3872
+
3873
+
3874
+	/**
3875
+	 * getter for the protected $_views property
3876
+	 *
3877
+	 * @return array
3878
+	 */
3879
+	public function get_views(): array
3880
+	{
3881
+		return $this->_views;
3882
+	}
3883
+
3884
+
3885
+	/**
3886
+	 * @param array $views
3887
+	 * @return void
3888
+	 * @since 5.0.13.p
3889
+	 */
3890
+	public function updateViews(array $views)
3891
+	{
3892
+		$this->_views = array_merge($this->_views, $views);
3893
+	}
3894
+
3895
+
3896
+	/**
3897
+    /**
3898
+	 * get_current_page
3899
+	 *
3900
+	 * @return string _current_page property value
3901
+	 */
3902
+	public function get_current_page(): string
3903
+	{
3904
+		return $this->_current_page;
3905
+	}
3906
+
3907
+
3908
+	/**
3909
+	 * get_current_view
3910
+	 *
3911
+	 * @return string _current_view property value
3912
+	 */
3913
+	public function get_current_view(): string
3914
+	{
3915
+		return $this->_current_view;
3916
+	}
3917
+
3918
+
3919
+	/**
3920
+	 * get_current_screen
3921
+	 *
3922
+	 * @return object The current WP_Screen object
3923
+	 */
3924
+	public function get_current_screen()
3925
+	{
3926
+		return $this->_current_screen;
3927
+	}
3928
+
3929
+
3930
+	/**
3931
+	 * get_current_page_view_url
3932
+	 *
3933
+	 * @return string This returns the url for the current_page_view.
3934
+	 */
3935
+	public function get_current_page_view_url(): string
3936
+	{
3937
+		return $this->_current_page_view_url;
3938
+	}
3939
+
3940
+
3941
+	/**
3942
+	 * just returns the Request
3943
+	 *
3944
+	 * @return RequestInterface
3945
+	 */
3946
+	public function get_request(): ?RequestInterface
3947
+	{
3948
+		return $this->request;
3949
+	}
3950
+
3951
+
3952
+	/**
3953
+	 * just returns the _req_data property
3954
+	 *
3955
+	 * @return array
3956
+	 */
3957
+	public function get_request_data(): array
3958
+	{
3959
+		return $this->request->requestParams();
3960
+	}
3961
+
3962
+
3963
+	/**
3964
+	 * returns the _req_data protected property
3965
+	 *
3966
+	 * @return string
3967
+	 */
3968
+	public function get_req_action(): string
3969
+	{
3970
+		return $this->_req_action;
3971
+	}
3972
+
3973
+
3974
+	/**
3975
+	 * @return bool  value of $_is_caf property
3976
+	 */
3977
+	public function is_caf(): bool
3978
+	{
3979
+		return $this->_is_caf;
3980
+	}
3981
+
3982
+
3983
+	/**
3984
+	 * @return array
3985
+	 */
3986
+	public function default_espresso_metaboxes(): array
3987
+	{
3988
+		return $this->_default_espresso_metaboxes;
3989
+	}
3990
+
3991
+
3992
+	/**
3993
+	 * @return string
3994
+	 */
3995
+	public function admin_base_url(): string
3996
+	{
3997
+		return $this->_admin_base_url;
3998
+	}
3999
+
4000
+
4001
+	/**
4002
+	 * @return string
4003
+	 */
4004
+	public function wp_page_slug(): string
4005
+	{
4006
+		return $this->_wp_page_slug;
4007
+	}
4008
+
4009
+
4010
+	/**
4011
+	 * updates  espresso configuration settings
4012
+	 *
4013
+	 * @param string                   $tab
4014
+	 * @param EE_Config_Base|EE_Config $config
4015
+	 * @param string                   $file file where error occurred
4016
+	 * @param string                   $func function  where error occurred
4017
+	 * @param string                   $line line no where error occurred
4018
+	 * @return bool
4019
+	 */
4020
+	protected function _update_espresso_configuration(
4021
+		string $tab,
4022
+		$config,
4023
+		string $file = '',
4024
+		string $func = '',
4025
+		string $line = ''
4026
+	): bool {
4027
+		// remove any options that are NOT going to be saved with the config settings.
4028
+		if (isset($config->core->ee_ueip_optin)) {
4029
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
4030
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4031
+			update_option('ee_ueip_has_notified', true);
4032
+		}
4033
+		// and save it (note we're also doing the network save here)
4034
+		$net_saved    = ! is_main_site() || EE_Network_Config::instance()->update_config(false, false);
4035
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4036
+		if ($config_saved && $net_saved) {
4037
+			EE_Error::add_success(sprintf(esc_html__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4038
+			return true;
4039
+		}
4040
+		EE_Error::add_error(
4041
+			sprintf(esc_html__('The "%s" were not updated.', 'event_espresso'), $tab),
4042
+			$file,
4043
+			$func,
4044
+			$line
4045
+		);
4046
+		return false;
4047
+	}
4048
+
4049
+
4050
+	/**
4051
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4052
+	 *
4053
+	 * @return array
4054
+	 */
4055
+	public function get_yes_no_values(): array
4056
+	{
4057
+		return $this->_yes_no_values;
4058
+	}
4059
+
4060
+
4061
+	/**
4062
+	 * @return string
4063
+	 * @throws ReflectionException
4064
+	 * @since 5.0.0.p
4065
+	 */
4066
+	protected function _get_dir(): string
4067
+	{
4068
+		$reflector = new ReflectionClass($this->class_name);
4069
+		return dirname($reflector->getFileName());
4070
+	}
4071
+
4072
+
4073
+	/**
4074
+	 * A helper for getting a "next link".
4075
+	 *
4076
+	 * @param string $url   The url to link to
4077
+	 * @param string $class The class to use.
4078
+	 * @return string
4079
+	 */
4080
+	protected function _next_link(string $url, string $class = 'dashicons dashicons-arrow-right'): string
4081
+	{
4082
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4083
+	}
4084
+
4085
+
4086
+	/**
4087
+	 * A helper for getting a "previous link".
4088
+	 *
4089
+	 * @param string $url   The url to link to
4090
+	 * @param string $class The class to use.
4091
+	 * @return string
4092
+	 */
4093
+	protected function _previous_link(string $url, string $class = 'dashicons dashicons-arrow-left'): string
4094
+	{
4095
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4096
+	}
4097
+
4098
+
4099
+
4100
+
4101
+
4102
+
4103
+
4104
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4105
+
4106
+
4107
+	/**
4108
+	 * This processes a request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4109
+	 * 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
4110
+	 * _req_data array.
4111
+	 *
4112
+	 * @return bool success/fail
4113
+	 * @throws EE_Error
4114
+	 * @throws InvalidArgumentException
4115
+	 * @throws ReflectionException
4116
+	 * @throws InvalidDataTypeException
4117
+	 * @throws InvalidInterfaceException
4118
+	 */
4119
+	protected function _process_resend_registration(): bool
4120
+	{
4121
+		$this->_template_args['success'] = EED_Messages::process_resend($this->request->requestParams());
4122
+		do_action(
4123
+			'AHEE__EE_Admin_Page___process_resend_registration',
4124
+			$this->_template_args['success'],
4125
+			$this->request->requestParams()
4126
+		);
4127
+		return $this->_template_args['success'];
4128
+	}
4129
+
4130
+
4131
+	/**
4132
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4133
+	 *
4134
+	 * @param EE_Payment $payment
4135
+	 * @return bool success/fail
4136
+	 */
4137
+	protected function _process_payment_notification(EE_Payment $payment): bool
4138
+	{
4139
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4140
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4141
+		$this->_template_args['success'] = apply_filters(
4142
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4143
+			false,
4144
+			$payment
4145
+		);
4146
+		return $this->_template_args['success'];
4147
+	}
4148
+
4149
+
4150
+	/**
4151
+	 * @param EEM_Base      $entity_model
4152
+	 * @param string        $entity_PK_name name of the primary key field used as a request param, ie: id, ID, etc
4153
+	 * @param string        $action         one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4154
+	 * @param string        $delete_column  name of the field that denotes whether entity is trashed
4155
+	 * @param callable|null $callback       called after entity is trashed, restored, or deleted
4156
+	 * @return int|float
4157
+	 * @throws EE_Error
4158
+	 */
4159
+	protected function trashRestoreDeleteEntities(
4160
+		EEM_Base $entity_model,
4161
+		string $entity_PK_name,
4162
+		string $action = EE_Admin_List_Table::ACTION_DELETE,
4163
+		string $delete_column = '',
4164
+		?callable $callback = null
4165
+	) {
4166
+		$entity_PK      = $entity_model->get_primary_key_field();
4167
+		$entity_PK_name = $entity_PK_name ?: $entity_PK->get_name();
4168
+		$entity_PK_type = $this->resolveEntityFieldDataType($entity_PK);
4169
+		// grab ID if deleting a single entity
4170
+		if ($this->request->requestParamIsSet($entity_PK_name)) {
4171
+			$ID = $this->request->getRequestParam($entity_PK_name, 0, $entity_PK_type);
4172
+			return $this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback) ? 1 : 0;
4173
+		}
4174
+		// or grab checkbox array if bulk deleting
4175
+		$checkboxes = $this->request->getRequestParam('checkbox', [], $entity_PK_type, true);
4176
+		if (empty($checkboxes)) {
4177
+			return 0;
4178
+		}
4179
+		$success = 0;
4180
+		$IDs     = array_keys($checkboxes);
4181
+		// cycle thru bulk action checkboxes
4182
+		foreach ($IDs as $ID) {
4183
+			// increment $success
4184
+			if ($this->trashRestoreDeleteEntity($entity_model, $ID, $action, $delete_column, $callback)) {
4185
+				$success++;
4186
+			}
4187
+		}
4188
+		$count = (int) count($checkboxes);
4189
+		// if multiple entities were deleted successfully, then $deleted will be full count of deletions,
4190
+		// otherwise it will be a fraction of ( actual deletions / total entities to be deleted )
4191
+		return $success === $count ? $count : $success / $count;
4192
+	}
4193
+
4194
+
4195
+	/**
4196
+	 * @param EE_Primary_Key_Field_Base $entity_PK
4197
+	 * @return string
4198
+	 * @throws EE_Error
4199
+	 * @since   4.10.30.p
4200
+	 */
4201
+	private function resolveEntityFieldDataType(EE_Primary_Key_Field_Base $entity_PK): string
4202
+	{
4203
+		$entity_PK_type = $entity_PK->getSchemaType();
4204
+		switch ($entity_PK_type) {
4205
+			case 'boolean':
4206
+				return DataType::BOOL;
4207
+			case 'integer':
4208
+				return DataType::INT;
4209
+			case 'number':
4210
+				return DataType::FLOAT;
4211
+			case 'string':
4212
+				return DataType::STRING;
4213
+		}
4214
+		throw new RuntimeException(
4215
+			sprintf(
4216
+				esc_html__(
4217
+					'"%1$s" is an invalid schema type for the %2$s primary key.',
4218
+					'event_espresso'
4219
+				),
4220
+				$entity_PK_type,
4221
+				$entity_PK->get_name()
4222
+			)
4223
+		);
4224
+	}
4225
+
4226
+
4227
+	/**
4228
+	 * @param EEM_Base      $entity_model
4229
+	 * @param int|string    $entity_ID
4230
+	 * @param string        $action        one of the EE_Admin_List_Table::ACTION_* constants: delete, restore, trash
4231
+	 * @param string        $delete_column name of the field that denotes whether entity is trashed
4232
+	 * @param callable|null $callback      called after entity is trashed, restored, or deleted
4233
+	 * @return bool
4234
+	 */
4235
+	protected function trashRestoreDeleteEntity(
4236
+		EEM_Base $entity_model,
4237
+		$entity_ID,
4238
+		string $action,
4239
+		string $delete_column,
4240
+		?callable $callback = null
4241
+	): bool {
4242
+		$entity_ID = absint($entity_ID);
4243
+		if (! $entity_ID) {
4244
+			$this->trashRestoreDeleteError($action, $entity_model);
4245
+		}
4246
+		$result = 0;
4247
+		try {
4248
+			$entity = $entity_model->get_one_by_ID($entity_ID);
4249
+			if (! $entity instanceof EE_Base_Class) {
4250
+				throw new DomainException(
4251
+					sprintf(
4252
+						esc_html__(
4253
+							'Missing or invalid %1$s entity with ID of "%2$s" returned from db.',
4254
+							'event_espresso'
4255
+						),
4256
+						str_replace('EEM_', '', $entity_model->get_this_model_name()),
4257
+						$entity_ID
4258
+					)
4259
+				);
4260
+			}
4261
+			switch ($action) {
4262
+				case EE_Admin_List_Table::ACTION_DELETE:
4263
+					$result = (bool) $entity->delete_permanently();
4264
+					break;
4265
+				case EE_Admin_List_Table::ACTION_RESTORE:
4266
+					$result = $entity->delete_or_restore(false);
4267
+					break;
4268
+				case EE_Admin_List_Table::ACTION_TRASH:
4269
+					$result = $entity->delete_or_restore();
4270
+					break;
4271
+			}
4272
+		} catch (Exception $exception) {
4273
+			$this->trashRestoreDeleteError($action, $entity_model, $exception);
4274
+		}
4275
+		if (is_callable($callback)) {
4276
+			call_user_func_array($callback, [$entity_model, $entity_ID, $action, $result, $delete_column]);
4277
+		}
4278
+		return $result;
4279
+	}
4280
+
4281
+
4282
+	/**
4283
+	 * @param EEM_Base $entity_model
4284
+	 * @param string   $delete_column
4285
+	 * @since 4.10.30.p
4286
+	 */
4287
+	private function validateDeleteColumn(EEM_Base $entity_model, string $delete_column)
4288
+	{
4289
+		if (empty($delete_column)) {
4290
+			throw new DomainException(
4291
+				sprintf(
4292
+					esc_html__(
4293
+						'You need to specify the name of the "delete column" on the %2$s model, in order to trash or restore an entity.',
4294
+						'event_espresso'
4295
+					),
4296
+					$entity_model->get_this_model_name()
4297
+				)
4298
+			);
4299
+		}
4300
+		if (! $entity_model->has_field($delete_column)) {
4301
+			throw new DomainException(
4302
+				sprintf(
4303
+					esc_html__(
4304
+						'The %1$s field does not exist on the %2$s model.',
4305
+						'event_espresso'
4306
+					),
4307
+					$delete_column,
4308
+					$entity_model->get_this_model_name()
4309
+				)
4310
+			);
4311
+		}
4312
+	}
4313
+
4314
+
4315
+	/**
4316
+	 * @param EEM_Base       $entity_model
4317
+	 * @param Exception|null $exception
4318
+	 * @param string         $action
4319
+	 * @since 4.10.30.p
4320
+	 */
4321
+	private function trashRestoreDeleteError(string $action, EEM_Base $entity_model, Exception $exception = null)
4322
+	{
4323
+		if ($exception instanceof Exception) {
4324
+			throw new RuntimeException(
4325
+				sprintf(
4326
+					esc_html__(
4327
+						'Could not %1$s the %2$s because the following error occurred: %3$s',
4328
+						'event_espresso'
4329
+					),
4330
+					$action,
4331
+					$entity_model->get_this_model_name(),
4332
+					$exception->getMessage()
4333
+				)
4334
+			);
4335
+		}
4336
+		throw new RuntimeException(
4337
+			sprintf(
4338
+				esc_html__(
4339
+					'Could not %1$s the %2$s because an invalid ID was received.',
4340
+					'event_espresso'
4341
+				),
4342
+				$action,
4343
+				$entity_model->get_this_model_name()
4344
+			)
4345
+		);
4346
+	}
4347 4347
 }
Please login to merge, or discard this patch.
Spacing   +183 added lines, -183 removed lines patch added patch discarded remove patch
@@ -24,23 +24,23 @@  discard block
 block discarded – undo
24 24
  */
25 25
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
26 26
 {
27
-    protected ?EE_Admin_Config $admin_config       = null;
27
+    protected ?EE_Admin_Config $admin_config = null;
28 28
 
29
-    protected ?EE_Admin_Hooks $_hook_obj          = null;
29
+    protected ?EE_Admin_Hooks $_hook_obj = null;
30 30
 
31 31
     protected ?EE_Admin_List_Table $_list_table_object = null;
32 32
 
33
-    protected ?EE_Capabilities $capabilities       = null;
33
+    protected ?EE_Capabilities $capabilities = null;
34 34
 
35
-    protected ?EE_Registry $EE                 = null;
35
+    protected ?EE_Registry $EE = null;
36 36
 
37
-    protected ?FeatureFlags $feature            = null;
37
+    protected ?FeatureFlags $feature = null;
38 38
 
39
-    protected ?LoaderInterface $loader             = null;
39
+    protected ?LoaderInterface $loader = null;
40 40
 
41
-    protected ?RequestInterface $request            = null;
41
+    protected ?RequestInterface $request = null;
42 42
 
43
-    protected ?WP_Screen $_current_screen    = null;
43
+    protected ?WP_Screen $_current_screen = null;
44 44
 
45 45
     /**
46 46
      * @var array
@@ -124,7 +124,7 @@  discard block
 block discarded – undo
124 124
 
125 125
     protected string $_column_template_path = '';
126 126
 
127
-    protected bool $_cpt_route            = false;
127
+    protected bool $_cpt_route = false;
128 128
 
129 129
     /**
130 130
      * set via request page and action args.
@@ -245,7 +245,7 @@  discard block
 block discarded – undo
245 245
 
246 246
     public function capabilities(): EE_Capabilities
247 247
     {
248
-        if (! $this->capabilities instanceof EE_Capabilities) {
248
+        if ( ! $this->capabilities instanceof EE_Capabilities) {
249 249
             $this->capabilities = $this->loader->getShared(EE_Capabilities::class);
250 250
         }
251 251
         return $this->capabilities;
@@ -609,7 +609,7 @@  discard block
 block discarded – undo
609 609
         $ee_menu_slugs = (array) $ee_menu_slugs;
610 610
         if (
611 611
             ! $this->request->isAjax()
612
-            && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))
612
+            && ( ! $this->_current_page || ! isset($ee_menu_slugs[$this->_current_page]))
613 613
         ) {
614 614
             return;
615 615
         }
@@ -629,7 +629,7 @@  discard block
 block discarded – undo
629 629
             ? $route
630 630
             : $req_action;
631 631
         $this->_current_view = $this->_req_action;
632
-        $this->_req_nonce    = $this->_req_action . '_nonce';
632
+        $this->_req_nonce    = $this->_req_action.'_nonce';
633 633
         $this->_define_page_props();
634 634
         $this->_current_page_view_url = add_query_arg(
635 635
             ['page' => $this->_current_page, 'action' => $this->_current_view],
@@ -653,33 +653,33 @@  discard block
 block discarded – undo
653 653
         }
654 654
         // filter routes and page_config so addons can add their stuff. Filtering done per class
655 655
         $this->_page_routes = apply_filters(
656
-            'FHEE__' . $this->class_name . '__page_setup__page_routes',
656
+            'FHEE__'.$this->class_name.'__page_setup__page_routes',
657 657
             $this->_page_routes,
658 658
             $this
659 659
         );
660 660
         $this->_page_config = apply_filters(
661
-            'FHEE__' . $this->class_name . '__page_setup__page_config',
661
+            'FHEE__'.$this->class_name.'__page_setup__page_config',
662 662
             $this->_page_config,
663 663
             $this
664 664
         );
665 665
         if ($this->base_class_name !== '') {
666 666
             $this->_page_routes = apply_filters(
667
-                'FHEE__' . $this->base_class_name . '__page_setup__page_routes',
667
+                'FHEE__'.$this->base_class_name.'__page_setup__page_routes',
668 668
                 $this->_page_routes,
669 669
                 $this
670 670
             );
671 671
             $this->_page_config = apply_filters(
672
-                'FHEE__' . $this->base_class_name . '__page_setup__page_config',
672
+                'FHEE__'.$this->base_class_name.'__page_setup__page_config',
673 673
                 $this->_page_config,
674 674
                 $this
675 675
             );
676 676
         }
677 677
         // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
678 678
         // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
679
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
679
+        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view)) {
680 680
             add_action(
681 681
                 'AHEE__EE_Admin_Page__route_admin_request',
682
-                [$this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view],
682
+                [$this, 'AHEE__EE_Admin_Page__route_admin_request_'.$this->_current_view],
683 683
                 10,
684 684
                 2
685 685
             );
@@ -692,8 +692,8 @@  discard block
 block discarded – undo
692 692
             if ($this->_is_UI_request) {
693 693
                 // admin_init stuff - global, all views for this page class, specific view
694 694
                 add_action('admin_init', [$this, 'admin_init']);
695
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
696
-                    add_action('admin_init', [$this, 'admin_init_' . $this->_current_view], 15);
695
+                if (method_exists($this, 'admin_init_'.$this->_current_view)) {
696
+                    add_action('admin_init', [$this, 'admin_init_'.$this->_current_view], 15);
697 697
                 }
698 698
             } else {
699 699
                 // hijack regular WP loading and route admin request immediately
@@ -712,12 +712,12 @@  discard block
 block discarded – undo
712 712
      */
713 713
     private function _do_other_page_hooks()
714 714
     {
715
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, []);
715
+        $registered_pages = apply_filters('FHEE_do_other_page_hooks_'.$this->page_slug, []);
716 716
         foreach ($registered_pages as $page) {
717 717
             // now let's set up the file name and class that should be present
718 718
             $classname = str_replace('.class.php', '', $page);
719 719
             // autoloaders should take care of loading file
720
-            if (! class_exists($classname)) {
720
+            if ( ! class_exists($classname)) {
721 721
                 $error_msg[] = sprintf(
722 722
                     esc_html__(
723 723
                         'Something went wrong with loading the %s admin hooks page.',
@@ -734,7 +734,7 @@  discard block
 block discarded – undo
734 734
                                    ),
735 735
                                    $page,
736 736
                                    '<br />',
737
-                                   '<strong>' . $classname . '</strong>'
737
+                                   '<strong>'.$classname.'</strong>'
738 738
                                );
739 739
                 throw new EE_Error(implode('||', $error_msg));
740 740
             }
@@ -783,13 +783,13 @@  discard block
 block discarded – undo
783 783
         // load admin_notices - global, page class, and view specific
784 784
         add_action('admin_notices', [$this, 'admin_notices_global'], 5);
785 785
         add_action('admin_notices', [$this, 'admin_notices']);
786
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
787
-            add_action('admin_notices', [$this, 'admin_notices_' . $this->_current_view], 15);
786
+        if (method_exists($this, 'admin_notices_'.$this->_current_view)) {
787
+            add_action('admin_notices', [$this, 'admin_notices_'.$this->_current_view], 15);
788 788
         }
789 789
         // load network admin_notices - global, page class, and view specific
790 790
         add_action('network_admin_notices', [$this, 'network_admin_notices_global'], 5);
791
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
792
-            add_action('network_admin_notices', [$this, 'network_admin_notices_' . $this->_current_view]);
791
+        if (method_exists($this, 'network_admin_notices_'.$this->_current_view)) {
792
+            add_action('network_admin_notices', [$this, 'network_admin_notices_'.$this->_current_view]);
793 793
         }
794 794
         // this will save any per_page screen options if they are present
795 795
         $this->_set_per_page_screen_options();
@@ -915,7 +915,7 @@  discard block
 block discarded – undo
915 915
      */
916 916
     protected function _verify_routes(): bool
917 917
     {
918
-        if (! $this->_current_page && ! $this->request->isAjax()) {
918
+        if ( ! $this->_current_page && ! $this->request->isAjax()) {
919 919
             return false;
920 920
         }
921 921
         // check that the page_routes array is not empty
@@ -926,7 +926,7 @@  discard block
 block discarded – undo
926 926
                 $this->_admin_page_title
927 927
             );
928 928
             // developer error msg
929
-            $error_msg .= '||' . $error_msg
929
+            $error_msg .= '||'.$error_msg
930 930
                           . esc_html__(
931 931
                               ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
932 932
                               'event_espresso'
@@ -938,14 +938,14 @@  discard block
 block discarded – undo
938 938
         if (
939 939
             $this->_req_action === 'editpost'
940 940
             && ! isset($this->_page_routes['editpost'])
941
-            && isset($this->_page_routes[ $alt_edit_route ])
941
+            && isset($this->_page_routes[$alt_edit_route])
942 942
         ) {
943 943
             $this->_req_action = $alt_edit_route;
944 944
         }
945 945
         // and that the requested page route exists
946 946
         if (array_key_exists($this->_req_action, $this->_page_routes)) {
947
-            $this->_route        = $this->_page_routes[ $this->_req_action ];
948
-            $this->_route_config = $this->_page_config[ $this->_req_action ] ?? [];
947
+            $this->_route        = $this->_page_routes[$this->_req_action];
948
+            $this->_route_config = $this->_page_config[$this->_req_action] ?? [];
949 949
         } else {
950 950
             // user error msg
951 951
             $error_msg = sprintf(
@@ -956,7 +956,7 @@  discard block
 block discarded – undo
956 956
                 $this->_admin_page_title
957 957
             );
958 958
             // developer error msg
959
-            $error_msg .= '||' . $error_msg
959
+            $error_msg .= '||'.$error_msg
960 960
                           . sprintf(
961 961
                               esc_html__(
962 962
                                   ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
@@ -967,7 +967,7 @@  discard block
 block discarded – undo
967 967
             throw new EE_Error($error_msg);
968 968
         }
969 969
         // and that a default route exists
970
-        if (! array_key_exists('default', $this->_page_routes)) {
970
+        if ( ! array_key_exists('default', $this->_page_routes)) {
971 971
             // user error msg
972 972
             $error_msg = sprintf(
973 973
                 esc_html__(
@@ -977,7 +977,7 @@  discard block
 block discarded – undo
977 977
                 $this->_admin_page_title
978 978
             );
979 979
             // developer error msg
980
-            $error_msg .= '||' . $error_msg
980
+            $error_msg .= '||'.$error_msg
981 981
                           . esc_html__(
982 982
                               ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
983 983
                               'event_espresso'
@@ -1017,7 +1017,7 @@  discard block
 block discarded – undo
1017 1017
             $this->_admin_page_title
1018 1018
         );
1019 1019
         // developer error msg
1020
-        $error_msg .= '||' . $error_msg
1020
+        $error_msg .= '||'.$error_msg
1021 1021
                       . sprintf(
1022 1022
                           esc_html__(
1023 1023
                               ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
@@ -1045,7 +1045,7 @@  discard block
 block discarded – undo
1045 1045
     protected function _verify_nonce(string $nonce, string $nonce_ref)
1046 1046
     {
1047 1047
         // verify nonce against expected value
1048
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
1048
+        if ( ! wp_verify_nonce($nonce, $nonce_ref)) {
1049 1049
             // these are not the droids you are looking for !!!
1050 1050
             $msg = sprintf(
1051 1051
                 esc_html__('%sNonce Fail.%s', 'event_espresso'),
@@ -1062,7 +1062,7 @@  discard block
 block discarded – undo
1062 1062
                     __CLASS__
1063 1063
                 );
1064 1064
             }
1065
-            if (! $this->request->isAjax()) {
1065
+            if ( ! $this->request->isAjax()) {
1066 1066
                 wp_die($msg);
1067 1067
             }
1068 1068
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
@@ -1087,7 +1087,7 @@  discard block
 block discarded – undo
1087 1087
      */
1088 1088
     protected function _route_admin_request()
1089 1089
     {
1090
-        if (! $this->_is_UI_request) {
1090
+        if ( ! $this->_is_UI_request) {
1091 1091
             $this->_verify_routes();
1092 1092
         }
1093 1093
         $nonce_check = ! isset($this->_route_config['require_nonce']) || $this->_route_config['require_nonce'];
@@ -1107,7 +1107,7 @@  discard block
 block discarded – undo
1107 1107
 
1108 1108
         // action right before calling route
1109 1109
         // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1110
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1110
+        if ( ! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1111 1111
             do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1112 1112
         }
1113 1113
         // strip _wp_http_referer from the server REQUEST_URI
@@ -1122,7 +1122,7 @@  discard block
 block discarded – undo
1122 1122
         $this->request->setRequestParam('_wp_http_referer', $cleaner_request_uri, true);
1123 1123
         $this->request->setServerParam('REQUEST_URI', $cleaner_request_uri, true);
1124 1124
         $route_callback = [];
1125
-        if (! empty($func)) {
1125
+        if ( ! empty($func)) {
1126 1126
             if (is_array($func) && is_callable($func)) {
1127 1127
                 $route_callback = $func;
1128 1128
             } elseif (is_string($func)) {
@@ -1136,7 +1136,7 @@  discard block
 block discarded – undo
1136 1136
             }
1137 1137
             [$class, $method] = $route_callback;
1138 1138
             // is it neither a class method NOR a standalone function?
1139
-            if (! is_callable($route_callback)) {
1139
+            if ( ! is_callable($route_callback)) {
1140 1140
                 // user error msg
1141 1141
                 $error_msg = esc_html__(
1142 1142
                     'An error occurred. The  requested page route could not be found.',
@@ -1245,7 +1245,7 @@  discard block
 block discarded – undo
1245 1245
                 if (strpos($key, 'nonce') !== false) {
1246 1246
                     continue;
1247 1247
                 }
1248
-                $args[ 'wp_referer[' . $key . ']' ] = is_string($value) ? htmlspecialchars($value) : $value;
1248
+                $args['wp_referer['.$key.']'] = is_string($value) ? htmlspecialchars($value) : $value;
1249 1249
             }
1250 1250
         }
1251 1251
         return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce, $context);
@@ -1285,12 +1285,12 @@  discard block
 block discarded – undo
1285 1285
      */
1286 1286
     protected function _add_help_tabs()
1287 1287
     {
1288
-        if (isset($this->_page_config[ $this->_req_action ])) {
1289
-            $config = $this->_page_config[ $this->_req_action ];
1288
+        if (isset($this->_page_config[$this->_req_action])) {
1289
+            $config = $this->_page_config[$this->_req_action];
1290 1290
             // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1291 1291
             if (is_array($config) && isset($config['help_sidebar'])) {
1292 1292
                 // check that the callback given is valid
1293
-                if (! method_exists($this, $config['help_sidebar'])) {
1293
+                if ( ! method_exists($this, $config['help_sidebar'])) {
1294 1294
                     throw new EE_Error(
1295 1295
                         sprintf(
1296 1296
                             esc_html__(
@@ -1303,18 +1303,18 @@  discard block
 block discarded – undo
1303 1303
                     );
1304 1304
                 }
1305 1305
                 $content = apply_filters(
1306
-                    'FHEE__' . $this->class_name . '__add_help_tabs__help_sidebar',
1306
+                    'FHEE__'.$this->class_name.'__add_help_tabs__help_sidebar',
1307 1307
                     $this->{$config['help_sidebar']}()
1308 1308
                 );
1309 1309
                 $this->_current_screen->set_help_sidebar($content);
1310 1310
             }
1311
-            if (! isset($config['help_tabs'])) {
1311
+            if ( ! isset($config['help_tabs'])) {
1312 1312
                 return;
1313 1313
             } //no help tabs for this route
1314 1314
             foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1315 1315
                 // we're here so there ARE help tabs!
1316 1316
                 // make sure we've got what we need
1317
-                if (! isset($cfg['title'])) {
1317
+                if ( ! isset($cfg['title'])) {
1318 1318
                     throw new EE_Error(
1319 1319
                         esc_html__(
1320 1320
                             'The _page_config array is not set up properly for help tabs.  It is missing a title',
@@ -1322,7 +1322,7 @@  discard block
 block discarded – undo
1322 1322
                         )
1323 1323
                     );
1324 1324
                 }
1325
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1325
+                if ( ! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1326 1326
                     throw new EE_Error(
1327 1327
                         esc_html__(
1328 1328
                             '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',
@@ -1331,11 +1331,11 @@  discard block
 block discarded – undo
1331 1331
                     );
1332 1332
                 }
1333 1333
                 // first priority goes to content.
1334
-                if (! empty($cfg['content'])) {
1334
+                if ( ! empty($cfg['content'])) {
1335 1335
                     $content = $cfg['content'];
1336 1336
                     // second priority goes to filename
1337
-                } elseif (! empty($cfg['filename'])) {
1338
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1337
+                } elseif ( ! empty($cfg['filename'])) {
1338
+                    $file_path = $this->_get_dir().'/help_tabs/'.$cfg['filename'].'.help_tab.php';
1339 1339
                     // 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)
1340 1340
                     $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1341 1341
                                                              . basename($this->_get_dir())
@@ -1343,7 +1343,7 @@  discard block
 block discarded – undo
1343 1343
                                                              . $cfg['filename']
1344 1344
                                                              . '.help_tab.php' : $file_path;
1345 1345
                     // if file is STILL not readable then let's do an EE_Error so its more graceful than a fatal error.
1346
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1346
+                    if ( ! isset($cfg['callback']) && ! is_readable($file_path)) {
1347 1347
                         EE_Error::add_error(
1348 1348
                             sprintf(
1349 1349
                                 esc_html__(
@@ -1391,7 +1391,7 @@  discard block
 block discarded – undo
1391 1391
                     return;
1392 1392
                 }
1393 1393
                 // setup config array for help tab method
1394
-                $id  = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1394
+                $id  = $this->page_slug.'-'.$this->_req_action.'-'.$tab_id;
1395 1395
                 $_ht = [
1396 1396
                     'id'       => $id,
1397 1397
                     'title'    => $cfg['title'],
@@ -1417,8 +1417,8 @@  discard block
 block discarded – undo
1417 1417
             $qtips = (array) $this->_route_config['qtips'];
1418 1418
             // load qtip loader
1419 1419
             $path = [
1420
-                $this->_get_dir() . '/qtips/',
1421
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1420
+                $this->_get_dir().'/qtips/',
1421
+                EE_ADMIN_PAGES.basename($this->_get_dir()).'/qtips/',
1422 1422
             ];
1423 1423
             EEH_Qtip_Loader::instance()->register($qtips, $path);
1424 1424
         }
@@ -1440,7 +1440,7 @@  discard block
 block discarded – undo
1440 1440
         $i        = 0;
1441 1441
         $only_tab = count($this->_page_config) < 2;
1442 1442
         foreach ($this->_page_config as $slug => $config) {
1443
-            if (! is_array($config) || empty($config['nav'])) {
1443
+            if ( ! is_array($config) || empty($config['nav'])) {
1444 1444
                 continue;
1445 1445
             }
1446 1446
             // no nav tab for this config
@@ -1449,7 +1449,7 @@  discard block
 block discarded – undo
1449 1449
                 // nav tab is only to appear when route requested.
1450 1450
                 continue;
1451 1451
             }
1452
-            if (! $this->check_user_access($slug, true)) {
1452
+            if ( ! $this->check_user_access($slug, true)) {
1453 1453
                 // no nav tab because current user does not have access.
1454 1454
                 continue;
1455 1455
             }
@@ -1457,20 +1457,20 @@  discard block
 block discarded – undo
1457 1457
             $css_class .= $only_tab ? ' ee-only-tab' : '';
1458 1458
             $css_class .= " ee-nav-tab__$slug";
1459 1459
 
1460
-            $this->_nav_tabs[ $slug ] = [
1460
+            $this->_nav_tabs[$slug] = [
1461 1461
                 'url'       => $config['nav']['url'] ?? EE_Admin_Page::add_query_args_and_nonce(
1462 1462
                     ['action' => $slug],
1463 1463
                     $this->_admin_base_url
1464 1464
                 ),
1465 1465
                 'link_text' => $this->navTabLabel($config['nav'], $slug),
1466
-                'css_class' => $this->_req_action === $slug ? $css_class . ' nav-tab-active' : $css_class,
1466
+                'css_class' => $this->_req_action === $slug ? $css_class.' nav-tab-active' : $css_class,
1467 1467
                 'order'     => $config['nav']['order'] ?? $i,
1468 1468
             ];
1469 1469
             $i++;
1470 1470
         }
1471 1471
         // if $this->_nav_tabs is empty then lets set the default
1472 1472
         if (empty($this->_nav_tabs)) {
1473
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = [
1473
+            $this->_nav_tabs[$this->_default_nav_tab_name] = [
1474 1474
                 'url'       => $this->_admin_base_url,
1475 1475
                 'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1476 1476
                 'css_class' => 'nav-tab-active',
@@ -1486,11 +1486,11 @@  discard block
 block discarded – undo
1486 1486
     {
1487 1487
         $label = $nav_tab['label'] ?? ucwords(str_replace('_', ' ', $slug));
1488 1488
         $icon  = $nav_tab['icon'] ?? null;
1489
-        $icon  = $icon ? '<span class="dashicons ' . $icon . '"></span>' : '';
1489
+        $icon  = $icon ? '<span class="dashicons '.$icon.'"></span>' : '';
1490 1490
         return '
1491 1491
             <span class="ee-admin-screen-tab__label">
1492
-                ' . $icon . '
1493
-                <span class="ee-nav-label__text">' . $label . '</span>
1492
+                ' . $icon.'
1493
+                <span class="ee-nav-label__text">' . $label.'</span>
1494 1494
             </span>';
1495 1495
     }
1496 1496
 
@@ -1508,10 +1508,10 @@  discard block
 block discarded – undo
1508 1508
             foreach ($this->_route_config['labels'] as $label => $text) {
1509 1509
                 if (is_array($text)) {
1510 1510
                     foreach ($text as $sublabel => $subtext) {
1511
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1511
+                        $this->_labels[$label][$sublabel] = $subtext;
1512 1512
                     }
1513 1513
                 } else {
1514
-                    $this->_labels[ $label ] = $text;
1514
+                    $this->_labels[$label] = $text;
1515 1515
                 }
1516 1516
             }
1517 1517
         }
@@ -1533,8 +1533,8 @@  discard block
 block discarded – undo
1533 1533
     {
1534 1534
         // if no route_to_check is passed in then use the current route set via _req_action
1535 1535
         $action = $route_to_check ?: $this->_req_action;
1536
-        $capability = ! empty($this->_page_routes[ $action ]['capability'])
1537
-            ? $this->_page_routes[ $action ]['capability']
1536
+        $capability = ! empty($this->_page_routes[$action]['capability'])
1537
+            ? $this->_page_routes[$action]['capability']
1538 1538
             : null;
1539 1539
 
1540 1540
         if (empty($capability)) {
@@ -1584,14 +1584,14 @@  discard block
 block discarded – undo
1584 1584
         string $priority = 'default',
1585 1585
         ?array $callback_args = null
1586 1586
     ) {
1587
-        if (! (is_callable($callback) || ! function_exists($callback))) {
1587
+        if ( ! (is_callable($callback) || ! function_exists($callback))) {
1588 1588
             return;
1589 1589
         }
1590 1590
 
1591 1591
         add_meta_box($box_id, $title, $callback, $screen, $context, $priority, $callback_args);
1592 1592
         add_filter(
1593 1593
             "postbox_classes_{$this->_wp_page_slug}_$box_id",
1594
-            function ($classes) {
1594
+            function($classes) {
1595 1595
                 $classes[] = 'ee-admin-container';
1596 1596
                 return $classes;
1597 1597
             }
@@ -1682,8 +1682,8 @@  discard block
 block discarded – undo
1682 1682
             <div class="ee-notices"></div>
1683 1683
             <div class="ee-admin-dialog-container-inner-content"></div>
1684 1684
         </div>
1685
-        <span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()) . '</span>
1686
-        <input type="hidden" id="espresso_admin_current_page" value="' . esc_attr($this->_current_page) . '"/>';
1685
+        <span id="current_timezone" class="hidden">' . esc_html(EEH_DTT_Helper::get_timezone()).'</span>
1686
+        <input type="hidden" id="espresso_admin_current_page" value="' . esc_attr($this->_current_page).'"/>';
1687 1687
     }
1688 1688
 
1689 1689
 
@@ -1717,7 +1717,7 @@  discard block
 block discarded – undo
1717 1717
         // loop through the array and setup content
1718 1718
         foreach ($help_array as $trigger => $help) {
1719 1719
             // make sure the array is set up properly
1720
-            if (! isset($help['title'], $help['content'])) {
1720
+            if ( ! isset($help['title'], $help['content'])) {
1721 1721
                 throw new EE_Error(
1722 1722
                     esc_html__(
1723 1723
                         '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',
@@ -1731,8 +1731,8 @@  discard block
 block discarded – undo
1731 1731
                 'help_popup_title'   => $help['title'],
1732 1732
                 'help_popup_content' => $help['content'],
1733 1733
             ];
1734
-            $content       .= EEH_Template::display_template(
1735
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1734
+            $content .= EEH_Template::display_template(
1735
+                EE_ADMIN_TEMPLATE.'admin_help_popup.template.php',
1736 1736
                 $template_args,
1737 1737
                 true
1738 1738
             );
@@ -1754,15 +1754,15 @@  discard block
 block discarded – undo
1754 1754
     private function _get_help_content(): array
1755 1755
     {
1756 1756
         // what is the method we're looking for?
1757
-        $method_name = '_help_popup_content_' . $this->_req_action;
1757
+        $method_name = '_help_popup_content_'.$this->_req_action;
1758 1758
         // if method doesn't exist let's get out.
1759
-        if (! method_exists($this, $method_name)) {
1759
+        if ( ! method_exists($this, $method_name)) {
1760 1760
             return [];
1761 1761
         }
1762 1762
         // k we're good to go let's retrieve the help array
1763 1763
         $help_array = $this->{$method_name}();
1764 1764
         // make sure we've got an array!
1765
-        if (! is_array($help_array)) {
1765
+        if ( ! is_array($help_array)) {
1766 1766
             throw new EE_Error(
1767 1767
                 esc_html__(
1768 1768
                     'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
@@ -1794,15 +1794,15 @@  discard block
 block discarded – undo
1794 1794
         // 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
1795 1795
         $help_array   = $this->_get_help_content();
1796 1796
         $help_content = '';
1797
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1798
-            $help_array[ $trigger_id ] = [
1797
+        if (empty($help_array) || ! isset($help_array[$trigger_id])) {
1798
+            $help_array[$trigger_id] = [
1799 1799
                 'title'   => esc_html__('Missing Content', 'event_espresso'),
1800 1800
                 'content' => esc_html__(
1801 1801
                     '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.)',
1802 1802
                     'event_espresso'
1803 1803
                 ),
1804 1804
             ];
1805
-            $help_content              = $this->_set_help_popup_content($help_array);
1805
+            $help_content = $this->_set_help_popup_content($help_array);
1806 1806
         }
1807 1807
         $height   = esc_attr($dimensions[0]) ?? 400;
1808 1808
         $width    = esc_attr($dimensions[1]) ?? 640;
@@ -1890,7 +1890,7 @@  discard block
 block discarded – undo
1890 1890
 
1891 1891
         add_filter(
1892 1892
             'admin_body_class',
1893
-            function ($classes) {
1893
+            function($classes) {
1894 1894
                 if (strpos($classes, 'espresso-admin') === false) {
1895 1895
                     $classes .= ' espresso-admin';
1896 1896
                 }
@@ -1981,12 +1981,12 @@  discard block
 block discarded – undo
1981 1981
     protected function _set_list_table()
1982 1982
     {
1983 1983
         // first is this a list_table view?
1984
-        if (! isset($this->_route_config['list_table'])) {
1984
+        if ( ! isset($this->_route_config['list_table'])) {
1985 1985
             return;
1986 1986
         } //not a list_table view so get out.
1987 1987
         // list table functions are per view specific (because some admin pages might have more than one list table!)
1988
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
1989
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1988
+        $list_table_view = '_set_list_table_views_'.$this->_req_action;
1989
+        if ( ! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
1990 1990
             // user error msg
1991 1991
             $error_msg = esc_html__(
1992 1992
                 'An error occurred. The requested list table views could not be found.',
@@ -2006,10 +2006,10 @@  discard block
 block discarded – undo
2006 2006
         }
2007 2007
         // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2008 2008
         $this->_views = apply_filters(
2009
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2009
+            'FHEE_list_table_views_'.$this->page_slug.'_'.$this->_req_action,
2010 2010
             $this->_views
2011 2011
         );
2012
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2012
+        $this->_views = apply_filters('FHEE_list_table_views_'.$this->page_slug, $this->_views);
2013 2013
         $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2014 2014
         $this->_set_list_table_view();
2015 2015
         $this->_set_list_table_object();
@@ -2044,7 +2044,7 @@  discard block
 block discarded – undo
2044 2044
     protected function _set_list_table_object()
2045 2045
     {
2046 2046
         if (isset($this->_route_config['list_table'])) {
2047
-            if (! class_exists($this->_route_config['list_table'])) {
2047
+            if ( ! class_exists($this->_route_config['list_table'])) {
2048 2048
                 throw new EE_Error(
2049 2049
                     sprintf(
2050 2050
                         esc_html__(
@@ -2086,16 +2086,16 @@  discard block
 block discarded – undo
2086 2086
         foreach ($this->_views as $key => $view) {
2087 2087
             $query_args = [];
2088 2088
             // check for current view
2089
-            $this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2089
+            $this->_views[$key]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2090 2090
             $query_args['action']          = $this->_req_action;
2091 2091
             $action_nonce                  = "{$this->_req_action}_nonce";
2092
-            $query_args[ $action_nonce ]   = wp_create_nonce($action_nonce);
2092
+            $query_args[$action_nonce]   = wp_create_nonce($action_nonce);
2093 2093
             $query_args['status']          = $view['slug'];
2094 2094
             // merge any other arguments sent in.
2095
-            if (isset($extra_query_args[ $view['slug'] ])) {
2096
-                $query_args = array_merge($query_args, $extra_query_args[ $view['slug'] ]);
2095
+            if (isset($extra_query_args[$view['slug']])) {
2096
+                $query_args = array_merge($query_args, $extra_query_args[$view['slug']]);
2097 2097
             }
2098
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2098
+            $this->_views[$key]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2099 2099
         }
2100 2100
         return $this->_views;
2101 2101
     }
@@ -2124,14 +2124,14 @@  discard block
 block discarded – undo
2124 2124
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2125 2125
         foreach ($values as $value) {
2126 2126
             if ($value < $max_entries) {
2127
-                $selected                  = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2127
+                $selected = $value === $per_page ? ' selected="'.$per_page.'"' : '';
2128 2128
                 $entries_per_page_dropdown .= '
2129
-						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2129
+						<option value="' . $value.'"'.$selected.'>'.$value.'&nbsp;&nbsp;</option>';
2130 2130
             }
2131 2131
         }
2132
-        $selected                  = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2132
+        $selected = $max_entries === $per_page ? ' selected="'.$per_page.'"' : '';
2133 2133
         $entries_per_page_dropdown .= '
2134
-						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2134
+						<option value="' . $max_entries.'"'.$selected.'>All&nbsp;&nbsp;</option>';
2135 2135
         $entries_per_page_dropdown .= '
2136 2136
 					</select>
2137 2137
 					entries
@@ -2155,7 +2155,7 @@  discard block
 block discarded – undo
2155 2155
             empty($this->_search_btn_label) ? $this->page_label
2156 2156
                 : $this->_search_btn_label
2157 2157
         );
2158
-        $this->_template_args['search']['callback']  = 'search_' . $this->page_slug;
2158
+        $this->_template_args['search']['callback'] = 'search_'.$this->page_slug;
2159 2159
     }
2160 2160
 
2161 2161
 
@@ -2216,7 +2216,7 @@  discard block
 block discarded – undo
2216 2216
                                   );
2217 2217
                     throw new EE_Error($error_msg);
2218 2218
                 }
2219
-                unset($this->_route_config['metaboxes'][ $key ]);
2219
+                unset($this->_route_config['metaboxes'][$key]);
2220 2220
             }
2221 2221
         }
2222 2222
     }
@@ -2249,7 +2249,7 @@  discard block
 block discarded – undo
2249 2249
             $total_columns                                       = ! empty($screen_columns)
2250 2250
                 ? $screen_columns
2251 2251
                 : $this->_route_config['columns'][1];
2252
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2252
+            $this->_template_args['current_screen_widget_class'] = 'columns-'.$total_columns;
2253 2253
             $this->_template_args['current_page']                = $this->_wp_page_slug;
2254 2254
             $this->_template_args['screen']                      = $this->_current_screen;
2255 2255
             $this->_column_template_path                         = EE_ADMIN_TEMPLATE
@@ -2295,7 +2295,7 @@  discard block
 block discarded – undo
2295 2295
      */
2296 2296
     protected function _espresso_ratings_request()
2297 2297
     {
2298
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2298
+        if ( ! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2299 2299
             return;
2300 2300
         }
2301 2301
         $ratings_box_title = apply_filters(
@@ -2322,28 +2322,28 @@  discard block
 block discarded – undo
2322 2322
      */
2323 2323
     public function espresso_ratings_request()
2324 2324
     {
2325
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2325
+        EEH_Template::display_template(EE_ADMIN_TEMPLATE.'espresso_ratings_request_content.template.php');
2326 2326
     }
2327 2327
 
2328 2328
 
2329 2329
     public static function cached_rss_display(string $rss_id, string $url): bool
2330 2330
     {
2331
-        $loading   = '<p class="widget-loading hide-if-no-js">'
2331
+        $loading = '<p class="widget-loading hide-if-no-js">'
2332 2332
                      . esc_html__('Loading&#8230;', 'event_espresso')
2333 2333
                      . '</p><p class="hide-if-js">'
2334 2334
                      . esc_html__('This widget requires JavaScript.', 'event_espresso')
2335 2335
                      . '</p>';
2336
-        $pre       = '<div class="espresso-rss-display">' . "\n\t";
2337
-        $pre       .= '<span id="' . esc_attr($rss_id) . '_url" class="hidden">' . esc_url_raw($url) . '</span>';
2338
-        $post      = '</div>' . "\n";
2339
-        $cache_key = 'ee_rss_' . md5($rss_id);
2336
+        $pre       = '<div class="espresso-rss-display">'."\n\t";
2337
+        $pre .= '<span id="'.esc_attr($rss_id).'_url" class="hidden">'.esc_url_raw($url).'</span>';
2338
+        $post      = '</div>'."\n";
2339
+        $cache_key = 'ee_rss_'.md5($rss_id);
2340 2340
         $output    = get_transient($cache_key);
2341 2341
         if ($output !== false) {
2342
-            echo wp_kses($pre . $output . $post, AllowedTags::getWithFormTags());
2342
+            echo wp_kses($pre.$output.$post, AllowedTags::getWithFormTags());
2343 2343
             return true;
2344 2344
         }
2345
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2346
-            echo wp_kses($pre . $loading . $post, AllowedTags::getWithFormTags());
2345
+        if ( ! (defined('DOING_AJAX') && DOING_AJAX)) {
2346
+            echo wp_kses($pre.$loading.$post, AllowedTags::getWithFormTags());
2347 2347
             return false;
2348 2348
         }
2349 2349
         ob_start();
@@ -2410,7 +2410,7 @@  discard block
 block discarded – undo
2410 2410
     public function espresso_sponsors_post_box()
2411 2411
     {
2412 2412
         EEH_Template::display_template(
2413
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2413
+            EE_ADMIN_TEMPLATE.'admin_general_metabox_contents_espresso_sponsors.template.php'
2414 2414
         );
2415 2415
     }
2416 2416
 
@@ -2427,9 +2427,9 @@  discard block
 block discarded – undo
2427 2427
     protected function getPublishBoxTitle(): string
2428 2428
     {
2429 2429
         $publish_box_title = esc_html__('Publish', 'event_espresso');
2430
-        if (! empty($this->_labels['publishbox'])) {
2430
+        if ( ! empty($this->_labels['publishbox'])) {
2431 2431
             if (is_array($this->_labels['publishbox'])) {
2432
-                $publish_box_title = $this->_labels['publishbox'][ $this->_req_action ] ?? $publish_box_title;
2432
+                $publish_box_title = $this->_labels['publishbox'][$this->_req_action] ?? $publish_box_title;
2433 2433
             } else {
2434 2434
                 $publish_box_title = $this->_labels['publishbox'];
2435 2435
             }
@@ -2479,7 +2479,7 @@  discard block
 block discarded – undo
2479 2479
         // if we have extra content set let's add it in if not make sure its empty
2480 2480
         $this->_template_args['publish_box_extra_content'] = $this->_template_args['publish_box_extra_content'] ?? '';
2481 2481
         echo EEH_Template::display_template(
2482
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2482
+            EE_ADMIN_TEMPLATE.'admin_details_publish_metabox.template.php',
2483 2483
             $this->_template_args,
2484 2484
             true
2485 2485
         );
@@ -2532,10 +2532,10 @@  discard block
 block discarded – undo
2532 2532
                 'submitdelete deletion button button--outline button--caution'
2533 2533
             );
2534 2534
         }
2535
-        if (! isset($this->_template_args['publish_delete_link'])) {
2535
+        if ( ! isset($this->_template_args['publish_delete_link'])) {
2536 2536
             $this->_template_args['publish_delete_link'] = '';
2537 2537
         }
2538
-        if (! empty($name) && ! empty($id)) {
2538
+        if ( ! empty($name) && ! empty($id)) {
2539 2539
             $this->addPublishPostMetaBoxHiddenFields($name, ['type' => 'hidden', 'value' => $id]);
2540 2540
         }
2541 2541
         $hidden_fields = $this->_generate_admin_form_fields($this->publish_post_meta_box_hidden_fields, 'array');
@@ -2568,7 +2568,7 @@  discard block
 block discarded – undo
2568 2568
 
2569 2569
     protected function addPublishPostMetaBoxHiddenFields(string $field_name, array $field_attributes)
2570 2570
     {
2571
-        $this->publish_post_meta_box_hidden_fields[ $field_name ] = $field_attributes;
2571
+        $this->publish_post_meta_box_hidden_fields[$field_name] = $field_attributes;
2572 2572
     }
2573 2573
 
2574 2574
 
@@ -2670,7 +2670,7 @@  discard block
 block discarded – undo
2670 2670
         }
2671 2671
         // 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)
2672 2672
         $call_back_func = $create_func
2673
-            ? static function ($post, $metabox) {
2673
+            ? static function($post, $metabox) {
2674 2674
                 echo EEH_Template::display_template(
2675 2675
                     $metabox['args']['template_path'],
2676 2676
                     $metabox['args']['template_args'],
@@ -2679,7 +2679,7 @@  discard block
 block discarded – undo
2679 2679
             }
2680 2680
             : $callback;
2681 2681
         $this->addMetaBox(
2682
-            str_replace('_', '-', $action) . '-mbox',
2682
+            str_replace('_', '-', $action).'-mbox',
2683 2683
             $title,
2684 2684
             $call_back_func,
2685 2685
             $this->_wp_page_slug,
@@ -2795,15 +2795,15 @@  discard block
 block discarded – undo
2795 2795
             'event-espresso_page_espresso_',
2796 2796
             '',
2797 2797
             $this->_wp_page_slug
2798
-        ) . ' ' . $this->_req_action . '-route';
2798
+        ).' '.$this->_req_action.'-route';
2799 2799
 
2800 2800
         $template_path = $sidebar
2801 2801
             ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2802
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2802
+            : EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar.template.php';
2803 2803
 
2804 2804
         $this->_template_args['is_ajax'] = $this->request->isAjax();
2805 2805
         if ($this->request->isAjax()) {
2806
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2806
+            $template_path = EE_ADMIN_TEMPLATE.'admin_details_wrapper_no_sidebar_ajax.template.php';
2807 2807
         }
2808 2808
         $template_path = ! empty($this->_column_template_path) ? $this->_column_template_path : $template_path;
2809 2809
 
@@ -2815,10 +2815,10 @@  discard block
 block discarded – undo
2815 2815
         // to prevent WooCommerce from blowing things up if not using CPT
2816 2816
         global $post_type, $post;
2817 2817
         $this->_template_args['post_type'] = $post_type ?? '';
2818
-        $this->_template_args['post']  = $post ?? new WP_Post((object) [ 'ID' => 0, 'filter' => 'raw' ]);
2818
+        $this->_template_args['post'] = $post ?? new WP_Post((object) ['ID' => 0, 'filter' => 'raw']);
2819 2819
 
2820 2820
         $this->_template_args['post_body_content'] = EEH_Template::display_template(
2821
-            EE_ADMIN_TEMPLATE . 'admin_details_wrapper_post_body_content.template.php',
2821
+            EE_ADMIN_TEMPLATE.'admin_details_wrapper_post_body_content.template.php',
2822 2822
             $this->_template_args,
2823 2823
             true
2824 2824
         );
@@ -2850,11 +2850,11 @@  discard block
 block discarded – undo
2850 2850
     public function display_admin_caf_preview_page(string $utm_campaign_source = '', bool $display_sidebar = true)
2851 2851
     {
2852 2852
         // let's generate a default preview action button if there isn't one already present.
2853
-        $this->_labels['buttons']['buy_now']           = esc_html__(
2853
+        $this->_labels['buttons']['buy_now'] = esc_html__(
2854 2854
             'Upgrade to Event Espresso 4 Right Now',
2855 2855
             'event_espresso'
2856 2856
         );
2857
-        $buy_now_url                                   = add_query_arg(
2857
+        $buy_now_url = add_query_arg(
2858 2858
             [
2859 2859
                 'ee_ver'       => 'ee4',
2860 2860
                 'utm_source'   => 'ee4_plugin_admin',
@@ -2874,8 +2874,8 @@  discard block
 block discarded – undo
2874 2874
                 true
2875 2875
             )
2876 2876
             : $this->_template_args['preview_action_button'];
2877
-        $this->_template_args['admin_page_content']    = EEH_Template::display_template(
2878
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2877
+        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2878
+            EE_ADMIN_TEMPLATE.'admin_caf_full_page_preview.template.php',
2879 2879
             $this->_template_args,
2880 2880
             true
2881 2881
         );
@@ -2933,7 +2933,7 @@  discard block
 block discarded – undo
2933 2933
         // setup search attributes
2934 2934
         $this->_set_search_attributes();
2935 2935
         $this->_template_args['current_page']     = $this->_wp_page_slug;
2936
-        $template_path                            = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2936
+        $template_path                            = EE_ADMIN_TEMPLATE.'admin_list_wrapper.template.php';
2937 2937
         $this->_template_args['table_url']        = $this->request->isAjax()
2938 2938
             ? add_query_arg(['noheader' => 'true', 'route' => $this->_req_action], $this->_admin_base_url)
2939 2939
             : add_query_arg(['route' => $this->_req_action], $this->_admin_base_url);
@@ -2941,10 +2941,10 @@  discard block
 block discarded – undo
2941 2941
         $this->_template_args['current_route']    = $this->_req_action;
2942 2942
         $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2943 2943
         $ajax_sorting_callback                    = $this->_list_table_object->get_ajax_sorting_callback();
2944
-        if (! empty($ajax_sorting_callback)) {
2944
+        if ( ! empty($ajax_sorting_callback)) {
2945 2945
             $sortable_list_table_form_fields = wp_nonce_field(
2946
-                $ajax_sorting_callback . '_nonce',
2947
-                $ajax_sorting_callback . '_nonce',
2946
+                $ajax_sorting_callback.'_nonce',
2947
+                $ajax_sorting_callback.'_nonce',
2948 2948
                 false,
2949 2949
                 false
2950 2950
             );
@@ -2961,18 +2961,18 @@  discard block
 block discarded – undo
2961 2961
 
2962 2962
         $hidden_form_fields = $this->_template_args['list_table_hidden_fields'] ?? '';
2963 2963
 
2964
-        $nonce_ref          = $this->_req_action . '_nonce';
2964
+        $nonce_ref          = $this->_req_action.'_nonce';
2965 2965
         $hidden_form_fields .= '
2966
-            <input type="hidden" name="' . $nonce_ref . '" value="' . wp_create_nonce($nonce_ref) . '">';
2966
+            <input type="hidden" name="' . $nonce_ref.'" value="'.wp_create_nonce($nonce_ref).'">';
2967 2967
 
2968 2968
         $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2969 2969
         // display message about search results?
2970
-        $search                                    = $this->request->getRequestParam('s');
2970
+        $search = $this->request->getRequestParam('s');
2971 2971
         $this->_template_args['before_list_table'] .= ! empty($search)
2972
-            ? '<p class="ee-search-results">' . sprintf(
2972
+            ? '<p class="ee-search-results">'.sprintf(
2973 2973
                 esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2974 2974
                 trim($search, '%')
2975
-            ) . '</p>'
2975
+            ).'</p>'
2976 2976
             : '';
2977 2977
         // filter before_list_table template arg
2978 2978
         $this->_template_args['before_list_table'] = apply_filters(
@@ -3006,7 +3006,7 @@  discard block
 block discarded – undo
3006 3006
         // convert to array and filter again
3007 3007
         // arrays are easier to inject new items in a specific location,
3008 3008
         // but would not be backwards compatible, so we have to add a new filter
3009
-        $this->_template_args['after_list_table']   = implode(
3009
+        $this->_template_args['after_list_table'] = implode(
3010 3010
             " \n",
3011 3011
             (array) apply_filters(
3012 3012
                 'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
@@ -3061,7 +3061,7 @@  discard block
 block discarded – undo
3061 3061
             $this->page_slug
3062 3062
         );
3063 3063
         return EEH_Template::display_template(
3064
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3064
+            EE_ADMIN_TEMPLATE.'admin_details_legend.template.php',
3065 3065
             $this->_template_args,
3066 3066
             true
3067 3067
         );
@@ -3184,7 +3184,7 @@  discard block
 block discarded – undo
3184 3184
         if ($this->request->isAjax()) {
3185 3185
             $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3186 3186
             // $template_path,
3187
-                EE_ADMIN_TEMPLATE . 'admin_wrapper_ajax.template.php',
3187
+                EE_ADMIN_TEMPLATE.'admin_wrapper_ajax.template.php',
3188 3188
                 $this->_template_args,
3189 3189
                 true
3190 3190
             );
@@ -3193,7 +3193,7 @@  discard block
 block discarded – undo
3193 3193
         // load settings page wrapper template
3194 3194
         $template_path = $about
3195 3195
             ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3196
-            : EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php';
3196
+            : EE_ADMIN_TEMPLATE.'admin_wrapper.template.php';
3197 3197
 
3198 3198
         EEH_Template::display_template($template_path, $this->_template_args);
3199 3199
     }
@@ -3277,12 +3277,12 @@  discard block
 block discarded – undo
3277 3277
         $default_names = ['save', 'save_and_close'];
3278 3278
         $buttons       = '';
3279 3279
         foreach ($button_text as $key => $button) {
3280
-            $ref     = $default_names[ $key ];
3281
-            $name    = ! empty($actions) ? $actions[ $key ] : $ref;
3282
-            $buttons .= '<input type="submit" class="button button--primary ' . $ref . '" '
3283
-                        . 'value="' . $button . '" name="' . $name . '" '
3284
-                        . 'id="' . $this->_current_view . '_' . $ref . '" />';
3285
-            if (! $both) {
3280
+            $ref     = $default_names[$key];
3281
+            $name    = ! empty($actions) ? $actions[$key] : $ref;
3282
+            $buttons .= '<input type="submit" class="button button--primary '.$ref.'" '
3283
+                        . 'value="'.$button.'" name="'.$name.'" '
3284
+                        . 'id="'.$this->_current_view.'_'.$ref.'" />';
3285
+            if ( ! $both) {
3286 3286
                 break;
3287 3287
             }
3288 3288
         }
@@ -3323,13 +3323,13 @@  discard block
 block discarded – undo
3323 3323
                 'An error occurred. No action was set for this page\'s form.',
3324 3324
                 'event_espresso'
3325 3325
             );
3326
-            $dev_msg  = $user_msg . "\n"
3326
+            $dev_msg = $user_msg."\n"
3327 3327
                         . sprintf(
3328 3328
                             esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3329 3329
                             __FUNCTION__,
3330 3330
                             __CLASS__
3331 3331
                         );
3332
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3332
+            EE_Error::add_error($user_msg.'||'.$dev_msg, __FILE__, __FUNCTION__, __LINE__);
3333 3333
         }
3334 3334
         // open form
3335 3335
         $action                                            = $this->_admin_base_url;
@@ -3337,9 +3337,9 @@  discard block
 block discarded – undo
3337 3337
             <form name='form' method='post' action='$action' id='{$route}_event_form' class='ee-admin-page-form' >
3338 3338
             ";
3339 3339
         // add nonce
3340
-        $nonce                                             =
3341
-            wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3342
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3340
+        $nonce =
3341
+            wp_nonce_field($route.'_nonce', $route.'_nonce', false, false);
3342
+        $this->_template_args['before_admin_page_content'] .= "\n\t".$nonce;
3343 3343
         // add REQUIRED form action
3344 3344
         $hidden_fields = [
3345 3345
             'action' => ['type' => 'hidden', 'value' => $route],
@@ -3352,7 +3352,7 @@  discard block
 block discarded – undo
3352 3352
         $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3353 3353
         // add fields to form
3354 3354
         foreach ((array) $form_fields as $form_field) {
3355
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3355
+            $this->_template_args['before_admin_page_content'] .= "\n\t".$form_field['field'];
3356 3356
         }
3357 3357
         // close form
3358 3358
         $this->_template_args['after_admin_page_content'] = '</form>';
@@ -3435,10 +3435,10 @@  discard block
 block discarded – undo
3435 3435
     ) {
3436 3436
         $notices = EE_Error::get_notices(false);
3437 3437
         // overwrite default success messages //BUT ONLY if overwrite not overridden
3438
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3438
+        if ( ! $override_overwrite || ! empty($notices['errors'])) {
3439 3439
             EE_Error::overwrite_success();
3440 3440
         }
3441
-        if (! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3441
+        if ( ! $override_overwrite && ! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3442 3442
             // how many records affected ? more than one record ? or just one ?
3443 3443
             EE_Error::add_success(
3444 3444
                 sprintf(
@@ -3489,7 +3489,7 @@  discard block
 block discarded – undo
3489 3489
             $redirect_url = admin_url('admin.php');
3490 3490
         }
3491 3491
         // merge any default query_args set in _default_route_query_args property
3492
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3492
+        if ( ! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3493 3493
             $args_to_merge = [];
3494 3494
             foreach ($this->_default_route_query_args as $query_param => $query_value) {
3495 3495
                 // is there a wp_referer array in our _default_route_query_args property?
@@ -3501,15 +3501,15 @@  discard block
 block discarded – undo
3501 3501
                         }
3502 3502
                         // finally we will override any arguments in the referer with
3503 3503
                         // what might be set on the _default_route_query_args array.
3504
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3505
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3504
+                        if (isset($this->_default_route_query_args[$reference])) {
3505
+                            $args_to_merge[$reference] = urlencode($this->_default_route_query_args[$reference]);
3506 3506
                         } else {
3507
-                            $args_to_merge[ $reference ] = urlencode($value);
3507
+                            $args_to_merge[$reference] = urlencode($value);
3508 3508
                         }
3509 3509
                     }
3510 3510
                     continue;
3511 3511
                 }
3512
-                $args_to_merge[ $query_param ] = $query_value;
3512
+                $args_to_merge[$query_param] = $query_value;
3513 3513
             }
3514 3514
             // now let's merge these arguments but override with what was specifically sent in to the
3515 3515
             // redirect.
@@ -3521,19 +3521,19 @@  discard block
 block discarded – undo
3521 3521
         if (isset($query_args['action'])) {
3522 3522
             // manually generate wp_nonce and merge that with the query vars
3523 3523
             // becuz the wp_nonce_url function wrecks havoc on some vars
3524
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3524
+            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'].'_nonce');
3525 3525
         }
3526 3526
         // we're adding some hooks and filters in here for processing any things just before redirects
3527 3527
         // (example: an admin page has done an insert or update and we want to run something after that).
3528
-        do_action('AHEE_redirect_' . $this->class_name . $this->_req_action, $query_args);
3528
+        do_action('AHEE_redirect_'.$this->class_name.$this->_req_action, $query_args);
3529 3529
         $redirect_url = apply_filters(
3530
-            'FHEE_redirect_' . $this->class_name . $this->_req_action,
3530
+            'FHEE_redirect_'.$this->class_name.$this->_req_action,
3531 3531
             EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3532 3532
             $query_args
3533 3533
         );
3534 3534
         // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3535 3535
         if ($this->request->isAjax()) {
3536
-            $default_data                    = [
3536
+            $default_data = [
3537 3537
                 'close'        => true,
3538 3538
                 'redirect_url' => $redirect_url,
3539 3539
                 'where'        => 'main',
@@ -3586,7 +3586,7 @@  discard block
 block discarded – undo
3586 3586
         }
3587 3587
         $this->_template_args['notices'] = EE_Error::get_notices();
3588 3588
         // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3589
-        if (! $this->request->isAjax() || $sticky_notices) {
3589
+        if ( ! $this->request->isAjax() || $sticky_notices) {
3590 3590
             $route = $query_args['action'] ?? 'default';
3591 3591
             $this->_add_transient(
3592 3592
                 $route,
@@ -3626,7 +3626,7 @@  discard block
 block discarded – undo
3626 3626
         bool $exclude_nonce = false
3627 3627
     ): string {
3628 3628
         // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3629
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3629
+        if (empty($base_url) && ! isset($this->_page_routes[$action])) {
3630 3630
             throw new EE_Error(
3631 3631
                 sprintf(
3632 3632
                     esc_html__(
@@ -3637,7 +3637,7 @@  discard block
 block discarded – undo
3637 3637
                 )
3638 3638
             );
3639 3639
         }
3640
-        if (! isset($this->_labels['buttons'][ $type ])) {
3640
+        if ( ! isset($this->_labels['buttons'][$type])) {
3641 3641
             throw new EE_Error(
3642 3642
                 sprintf(
3643 3643
                     esc_html__(
@@ -3650,7 +3650,7 @@  discard block
 block discarded – undo
3650 3650
         }
3651 3651
         // finally check user access for this button.
3652 3652
         $has_access = $this->check_user_access($action, true);
3653
-        if (! $has_access) {
3653
+        if ( ! $has_access) {
3654 3654
             return '';
3655 3655
         }
3656 3656
         $_base_url  = ! $base_url ? $this->_admin_base_url : $base_url;
@@ -3658,11 +3658,11 @@  discard block
 block discarded – undo
3658 3658
             'action' => $action,
3659 3659
         ];
3660 3660
         // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3661
-        if (! empty($extra_request)) {
3661
+        if ( ! empty($extra_request)) {
3662 3662
             $query_args = array_merge($extra_request, $query_args);
3663 3663
         }
3664 3664
         $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3665
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3665
+        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][$type], $class);
3666 3666
     }
3667 3667
 
3668 3668
 
@@ -3688,7 +3688,7 @@  discard block
 block discarded – undo
3688 3688
                 'FHEE__EE_Admin_Page___per_page_screen_options__default',
3689 3689
                 20
3690 3690
             ),
3691
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3691
+            'option'  => $this->_current_page.'_'.$this->_current_view.'_per_page',
3692 3692
         ];
3693 3693
         // ONLY add the screen option if the user has access to it.
3694 3694
         if ($this->check_user_access($this->_current_view, true)) {
@@ -3709,18 +3709,18 @@  discard block
 block discarded – undo
3709 3709
     {
3710 3710
         if ($this->request->requestParamIsSet('wp_screen_options')) {
3711 3711
             check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3712
-            if (! $user = wp_get_current_user()) {
3712
+            if ( ! $user = wp_get_current_user()) {
3713 3713
                 return;
3714 3714
             }
3715 3715
             $option = $this->request->getRequestParam('wp_screen_options[option]', '', DataType::KEY);
3716
-            if (! $option) {
3716
+            if ( ! $option) {
3717 3717
                 return;
3718 3718
             }
3719 3719
             $value      = $this->request->getRequestParam('wp_screen_options[value]', 0, DataType::INT);
3720 3720
             $map_option = $option;
3721 3721
             $option     = str_replace('-', '_', $option);
3722 3722
             switch ($map_option) {
3723
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3723
+                case $this->_current_page.'_'.$this->_current_view.'_per_page':
3724 3724
                     $max_value = apply_filters(
3725 3725
                         'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3726 3726
                         999,
@@ -3787,7 +3787,7 @@  discard block
 block discarded – undo
3787 3787
         bool $skip_route_verify = false
3788 3788
     ) {
3789 3789
         $user_id = get_current_user_id();
3790
-        if (! $skip_route_verify) {
3790
+        if ( ! $skip_route_verify) {
3791 3791
             $this->_verify_route($route);
3792 3792
         }
3793 3793
         // now let's set the string for what kind of transient we're setting
@@ -3820,8 +3820,8 @@  discard block
 block discarded – undo
3820 3820
         $user_id   = get_current_user_id();
3821 3821
         $route     = ! $route ? $this->_req_action : $route;
3822 3822
         $transient = $notices
3823
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3824
-            : 'rte_tx_' . $route . '_' . $user_id;
3823
+            ? 'ee_rte_n_tx_'.$route.'_'.$user_id
3824
+            : 'rte_tx_'.$route.'_'.$user_id;
3825 3825
         $data      = is_multisite() && is_network_admin()
3826 3826
             ? get_site_transient($transient)
3827 3827
             : get_transient($transient);
@@ -4079,7 +4079,7 @@  discard block
 block discarded – undo
4079 4079
      */
4080 4080
     protected function _next_link(string $url, string $class = 'dashicons dashicons-arrow-right'): string
4081 4081
     {
4082
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4082
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4083 4083
     }
4084 4084
 
4085 4085
 
@@ -4092,7 +4092,7 @@  discard block
 block discarded – undo
4092 4092
      */
4093 4093
     protected function _previous_link(string $url, string $class = 'dashicons dashicons-arrow-left'): string
4094 4094
     {
4095
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4095
+        return '<a class="'.$class.'" href="'.$url.'"></a>';
4096 4096
     }
4097 4097
 
4098 4098
 
@@ -4240,13 +4240,13 @@  discard block
 block discarded – undo
4240 4240
         ?callable $callback = null
4241 4241
     ): bool {
4242 4242
         $entity_ID = absint($entity_ID);
4243
-        if (! $entity_ID) {
4243
+        if ( ! $entity_ID) {
4244 4244
             $this->trashRestoreDeleteError($action, $entity_model);
4245 4245
         }
4246 4246
         $result = 0;
4247 4247
         try {
4248 4248
             $entity = $entity_model->get_one_by_ID($entity_ID);
4249
-            if (! $entity instanceof EE_Base_Class) {
4249
+            if ( ! $entity instanceof EE_Base_Class) {
4250 4250
                 throw new DomainException(
4251 4251
                     sprintf(
4252 4252
                         esc_html__(
@@ -4297,7 +4297,7 @@  discard block
 block discarded – undo
4297 4297
                 )
4298 4298
             );
4299 4299
         }
4300
-        if (! $entity_model->has_field($delete_column)) {
4300
+        if ( ! $entity_model->has_field($delete_column)) {
4301 4301
             throw new DomainException(
4302 4302
                 sprintf(
4303 4303
                     esc_html__(
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page_CPT.core.php 2 patches
Indentation   +1424 added lines, -1424 removed lines patch added patch discarded remove patch
@@ -31,450 +31,450 @@  discard block
 block discarded – undo
31 31
  */
32 32
 abstract class EE_Admin_Page_CPT extends EE_Admin_Page
33 33
 {
34
-    /**
35
-     * @var EE_CPT_Base|null
36
-     */
37
-    protected $_cpt_model_obj;
38
-
39
-    protected ?WP_Post_Type $_cpt_object = null;
40
-
41
-
42
-    /**
43
-     * This property allows cpt classes to define multiple routes as cpt routes.
44
-     * //in this array we define what the custom post type for this route is.
45
-     * array(
46
-     * 'route_name' => 'custom_post_type_slug'
47
-     * )
48
-     *
49
-     * @var array
50
-     */
51
-    protected array $_cpt_routes = [];
52
-
53
-
54
-    /**
55
-     * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
56
-     * in this format:
57
-     * array(
58
-     * 'post_type_slug' => 'edit_route'
59
-     * )
60
-     *
61
-     * @var array
62
-     */
63
-    protected array $_cpt_edit_routes = [];
64
-
65
-
66
-    /**
67
-     * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
68
-     * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
69
-     * _cpt_model_names property should be in the following format: array(
70
-     * 'route_defined_by_action_param' => 'Model_Name')
71
-     *
72
-     * @var array $_cpt_model_names
73
-     */
74
-    protected array $_cpt_model_names = [];
75
-
76
-
77
-    /**
78
-     * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
79
-     * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
80
-     * the _register_autosave_containers() method so that we don't override any other containers already registered.
81
-     * Registration of containers should be done before load_page_dependencies() is run.
82
-     *
83
-     * @var array
84
-     */
85
-    protected array $_autosave_containers = [];
86
-
87
-    protected array $_autosave_fields     = [];
88
-
89
-    /**
90
-     * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
91
-     * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
92
-     *
93
-     * @var array
94
-     */
95
-    protected array $_pagenow_map = [];
96
-
97
-
98
-    /**
99
-     * This is the route that will be used for the edit post route.
100
-     *
101
-     * @var string
102
-     */
103
-    protected string $cpt_editpost_route = 'edit';
104
-
105
-
106
-    /**
107
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
108
-     * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
109
-     * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
110
-     * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
111
-     * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
112
-     *
113
-     * @abstract
114
-     * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
115
-     * @param WP_Post $post    The post object of the cpt that was saved.
116
-     * @return void
117
-     */
118
-    abstract protected function _insert_update_cpt_item($post_id, $post);
119
-
120
-
121
-    /**
122
-     * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
123
-     *
124
-     * @abstract
125
-     * @param string $post_id The ID of the cpt that was trashed
126
-     * @return void
127
-     */
128
-    abstract public function trash_cpt_item($post_id);
129
-
130
-
131
-    /**
132
-     * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
133
-     *
134
-     * @param string $post_id theID of the cpt that was untrashed
135
-     * @return void
136
-     */
137
-    abstract public function restore_cpt_item($post_id);
138
-
139
-
140
-    /**
141
-     * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
142
-     * from the db
143
-     *
144
-     * @param string $post_id the ID of the cpt that was deleted
145
-     * @return void
146
-     */
147
-    abstract public function delete_cpt_item($post_id);
148
-
149
-
150
-    /**
151
-     * @return LoaderInterface
152
-     * @throws InvalidArgumentException
153
-     * @throws InvalidDataTypeException
154
-     * @throws InvalidInterfaceException
155
-     */
156
-    protected function getLoader(): LoaderInterface
157
-    {
158
-        if (! $this->loader instanceof LoaderInterface) {
159
-            $this->loader = LoaderFactory::getLoader();
160
-        }
161
-        return $this->loader;
162
-    }
163
-
164
-
165
-    /**
166
-     * Just utilizing the method EE_Admin exposes for doing things before page setup.
167
-     *
168
-     * @return void
169
-     */
170
-    protected function _before_page_setup()
171
-    {
172
-        $this->raw_req_action = $this->request->getRequestParam('action');
173
-        $this->raw_req_page   = $this->request->getRequestParam('page');
174
-        $this->_cpt_routes    = array_merge(
175
-            [
176
-                'create_new' => $this->page_slug,
177
-                'edit'       => $this->page_slug,
178
-                'trash'      => $this->page_slug,
179
-            ],
180
-            $this->_cpt_routes
181
-        );
182
-        $cpt_route_action     = $this->_cpt_routes[ $this->raw_req_action ] ?? null;
183
-        // let's see if the current route has a value for cpt_object_slug. if it does, we use that instead of the page
184
-        $page              = $this->raw_req_page ?: $this->page_slug;
185
-        $page              = $cpt_route_action ?: $page;
186
-        $this->_cpt_object = get_post_type_object($page);
187
-        // tweak pagenow for page loading.
188
-        if (empty($this->_pagenow_map)) {
189
-            $this->_pagenow_map = [
190
-                'create_new' => 'post-new.php',
191
-                'edit'       => 'post.php',
192
-                'trash'      => 'post.php',
193
-            ];
194
-        }
195
-        add_action('current_screen', [$this, 'modify_pagenow']);
196
-        // TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
197
-        // get current page from autosave
198
-        $current_page        = $this->request->getRequestParam('ee_autosave_data[ee-cpt-hidden-inputs][current_page]');
199
-        $this->_current_page = $this->request->getRequestParam('current_page', $current_page);
200
-    }
201
-
202
-
203
-    /**
204
-     * Simply ensure that we simulate the correct post route for cpt screens
205
-     *
206
-     * @param WP_Screen|null $current_screen
207
-     * @return void
208
-     */
209
-    public function modify_pagenow(?WP_Screen $current_screen)
210
-    {
211
-        // possibly reset pagenow.
212
-        if (
213
-            $this->page_slug === $this->raw_req_page
214
-            && isset($this->_pagenow_map[ $this->raw_req_action ])
215
-        ) {
216
-            global $pagenow, $hook_suffix;
217
-            $pagenow     = $this->_pagenow_map[ $this->raw_req_action ];
218
-            $hook_suffix = $pagenow;
219
-        }
220
-    }
221
-
222
-
223
-    /**
224
-     * This method is used to register additional autosave containers to the _autosave_containers property.
225
-     *
226
-     * @param array $ids  an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
227
-     *                    you would send along the id of a metabox container.
228
-     * @return void
229
-     * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
230
-     *                    automatically register the id for the post metabox as a container.
231
-     */
232
-    protected function _register_autosave_containers($ids)
233
-    {
234
-        $this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
235
-    }
236
-
237
-
238
-    /**
239
-     * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
240
-     * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
241
-     */
242
-    protected function _set_autosave_containers()
243
-    {
244
-        global $wp_meta_boxes;
245
-        $containers = [];
246
-        if (empty($wp_meta_boxes)) {
247
-            return;
248
-        }
249
-        $current_metaboxes = $wp_meta_boxes[ $this->page_slug ] ?? [];
250
-        foreach ($current_metaboxes as $box_context) {
251
-            foreach ($box_context as $box_details) {
252
-                foreach ($box_details as $box) {
253
-                    if (
254
-                        is_array($box) && is_array($box['callback'])
255
-                        && (
256
-                            $box['callback'][0] instanceof EE_Admin_Page
257
-                            || $box['callback'][0] instanceof EE_Admin_Hooks
258
-                        )
259
-                    ) {
260
-                        $containers[] = $box['id'];
261
-                    }
262
-                }
263
-            }
264
-        }
265
-        $this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
266
-        // add hidden inputs container
267
-        $this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
268
-    }
269
-
270
-
271
-    protected function _load_autosave_scripts_styles()
272
-    {
273
-        /*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
34
+	/**
35
+	 * @var EE_CPT_Base|null
36
+	 */
37
+	protected $_cpt_model_obj;
38
+
39
+	protected ?WP_Post_Type $_cpt_object = null;
40
+
41
+
42
+	/**
43
+	 * This property allows cpt classes to define multiple routes as cpt routes.
44
+	 * //in this array we define what the custom post type for this route is.
45
+	 * array(
46
+	 * 'route_name' => 'custom_post_type_slug'
47
+	 * )
48
+	 *
49
+	 * @var array
50
+	 */
51
+	protected array $_cpt_routes = [];
52
+
53
+
54
+	/**
55
+	 * This simply defines what the corresponding routes WP will be redirected to after completing a post save/update.
56
+	 * in this format:
57
+	 * array(
58
+	 * 'post_type_slug' => 'edit_route'
59
+	 * )
60
+	 *
61
+	 * @var array
62
+	 */
63
+	protected array $_cpt_edit_routes = [];
64
+
65
+
66
+	/**
67
+	 * If child classes set the name of their main model via the $_cpt_obj_models property, EE_Admin_Page_CPT will
68
+	 * attempt to retrieve the related object model for the edit pages and assign it to _cpt_page_object. the
69
+	 * _cpt_model_names property should be in the following format: array(
70
+	 * 'route_defined_by_action_param' => 'Model_Name')
71
+	 *
72
+	 * @var array $_cpt_model_names
73
+	 */
74
+	protected array $_cpt_model_names = [];
75
+
76
+
77
+	/**
78
+	 * This will hold an array of autosave containers that will be used to obtain input values and hook into the WP
79
+	 * autosave so we can save our inputs on the save_post hook!  Children classes should add to this array by using
80
+	 * the _register_autosave_containers() method so that we don't override any other containers already registered.
81
+	 * Registration of containers should be done before load_page_dependencies() is run.
82
+	 *
83
+	 * @var array
84
+	 */
85
+	protected array $_autosave_containers = [];
86
+
87
+	protected array $_autosave_fields     = [];
88
+
89
+	/**
90
+	 * Array mapping from admin actions to their equivalent wp core pages for custom post types. So when a user visits
91
+	 * a page for an action, it will appear as if they were visiting the wp core page for that custom post type
92
+	 *
93
+	 * @var array
94
+	 */
95
+	protected array $_pagenow_map = [];
96
+
97
+
98
+	/**
99
+	 * This is the route that will be used for the edit post route.
100
+	 *
101
+	 * @var string
102
+	 */
103
+	protected string $cpt_editpost_route = 'edit';
104
+
105
+
106
+	/**
107
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
108
+	 * saved.  Child classes are required to declare this method.  Typically you would use this to save any additional
109
+	 * data. Keep in mind also that "save_post" runs on EVERY post update to the database. ALSO very important.  When a
110
+	 * post transitions from scheduled to published, the save_post action is fired but you will NOT have any _POST data
111
+	 * containing any extra info you may have from other meta saves.  So MAKE sure that you handle this accordingly.
112
+	 *
113
+	 * @abstract
114
+	 * @param string  $post_id The ID of the cpt that was saved (so you can link relationally)
115
+	 * @param WP_Post $post    The post object of the cpt that was saved.
116
+	 * @return void
117
+	 */
118
+	abstract protected function _insert_update_cpt_item($post_id, $post);
119
+
120
+
121
+	/**
122
+	 * This is hooked into the WordPress do_action('trashed_post') hook and runs after a cpt has been trashed.
123
+	 *
124
+	 * @abstract
125
+	 * @param string $post_id The ID of the cpt that was trashed
126
+	 * @return void
127
+	 */
128
+	abstract public function trash_cpt_item($post_id);
129
+
130
+
131
+	/**
132
+	 * This is hooked into the WordPress do_action('untrashed_post') hook and runs after a cpt has been untrashed
133
+	 *
134
+	 * @param string $post_id theID of the cpt that was untrashed
135
+	 * @return void
136
+	 */
137
+	abstract public function restore_cpt_item($post_id);
138
+
139
+
140
+	/**
141
+	 * This is hooked into the WordPress do_action('delete_cpt_item') hook and runs after a cpt has been fully deleted
142
+	 * from the db
143
+	 *
144
+	 * @param string $post_id the ID of the cpt that was deleted
145
+	 * @return void
146
+	 */
147
+	abstract public function delete_cpt_item($post_id);
148
+
149
+
150
+	/**
151
+	 * @return LoaderInterface
152
+	 * @throws InvalidArgumentException
153
+	 * @throws InvalidDataTypeException
154
+	 * @throws InvalidInterfaceException
155
+	 */
156
+	protected function getLoader(): LoaderInterface
157
+	{
158
+		if (! $this->loader instanceof LoaderInterface) {
159
+			$this->loader = LoaderFactory::getLoader();
160
+		}
161
+		return $this->loader;
162
+	}
163
+
164
+
165
+	/**
166
+	 * Just utilizing the method EE_Admin exposes for doing things before page setup.
167
+	 *
168
+	 * @return void
169
+	 */
170
+	protected function _before_page_setup()
171
+	{
172
+		$this->raw_req_action = $this->request->getRequestParam('action');
173
+		$this->raw_req_page   = $this->request->getRequestParam('page');
174
+		$this->_cpt_routes    = array_merge(
175
+			[
176
+				'create_new' => $this->page_slug,
177
+				'edit'       => $this->page_slug,
178
+				'trash'      => $this->page_slug,
179
+			],
180
+			$this->_cpt_routes
181
+		);
182
+		$cpt_route_action     = $this->_cpt_routes[ $this->raw_req_action ] ?? null;
183
+		// let's see if the current route has a value for cpt_object_slug. if it does, we use that instead of the page
184
+		$page              = $this->raw_req_page ?: $this->page_slug;
185
+		$page              = $cpt_route_action ?: $page;
186
+		$this->_cpt_object = get_post_type_object($page);
187
+		// tweak pagenow for page loading.
188
+		if (empty($this->_pagenow_map)) {
189
+			$this->_pagenow_map = [
190
+				'create_new' => 'post-new.php',
191
+				'edit'       => 'post.php',
192
+				'trash'      => 'post.php',
193
+			];
194
+		}
195
+		add_action('current_screen', [$this, 'modify_pagenow']);
196
+		// TODO the below will need to be reworked to account for the cpt routes that are NOT based off of page but action param.
197
+		// get current page from autosave
198
+		$current_page        = $this->request->getRequestParam('ee_autosave_data[ee-cpt-hidden-inputs][current_page]');
199
+		$this->_current_page = $this->request->getRequestParam('current_page', $current_page);
200
+	}
201
+
202
+
203
+	/**
204
+	 * Simply ensure that we simulate the correct post route for cpt screens
205
+	 *
206
+	 * @param WP_Screen|null $current_screen
207
+	 * @return void
208
+	 */
209
+	public function modify_pagenow(?WP_Screen $current_screen)
210
+	{
211
+		// possibly reset pagenow.
212
+		if (
213
+			$this->page_slug === $this->raw_req_page
214
+			&& isset($this->_pagenow_map[ $this->raw_req_action ])
215
+		) {
216
+			global $pagenow, $hook_suffix;
217
+			$pagenow     = $this->_pagenow_map[ $this->raw_req_action ];
218
+			$hook_suffix = $pagenow;
219
+		}
220
+	}
221
+
222
+
223
+	/**
224
+	 * This method is used to register additional autosave containers to the _autosave_containers property.
225
+	 *
226
+	 * @param array $ids  an array of ids for containers that hold form inputs we want autosave to pickup.  Typically
227
+	 *                    you would send along the id of a metabox container.
228
+	 * @return void
229
+	 * @todo We should automate this at some point by creating a wrapper for add_post_metabox and in our wrapper we
230
+	 *                    automatically register the id for the post metabox as a container.
231
+	 */
232
+	protected function _register_autosave_containers($ids)
233
+	{
234
+		$this->_autosave_containers = array_merge($this->_autosave_fields, (array) $ids);
235
+	}
236
+
237
+
238
+	/**
239
+	 * Something nifty.  We're going to loop through all the registered metaboxes and if the CALLBACK is an instance of
240
+	 * EE_Admin_Page OR EE_Admin_Hooks, then we'll add the id to our _autosave_containers array.
241
+	 */
242
+	protected function _set_autosave_containers()
243
+	{
244
+		global $wp_meta_boxes;
245
+		$containers = [];
246
+		if (empty($wp_meta_boxes)) {
247
+			return;
248
+		}
249
+		$current_metaboxes = $wp_meta_boxes[ $this->page_slug ] ?? [];
250
+		foreach ($current_metaboxes as $box_context) {
251
+			foreach ($box_context as $box_details) {
252
+				foreach ($box_details as $box) {
253
+					if (
254
+						is_array($box) && is_array($box['callback'])
255
+						&& (
256
+							$box['callback'][0] instanceof EE_Admin_Page
257
+							|| $box['callback'][0] instanceof EE_Admin_Hooks
258
+						)
259
+					) {
260
+						$containers[] = $box['id'];
261
+					}
262
+				}
263
+			}
264
+		}
265
+		$this->_autosave_containers = array_merge($this->_autosave_containers, $containers);
266
+		// add hidden inputs container
267
+		$this->_autosave_containers[] = 'ee-cpt-hidden-inputs';
268
+	}
269
+
270
+
271
+	protected function _load_autosave_scripts_styles()
272
+	{
273
+		/*wp_register_script('cpt-autosave', EE_ADMIN_URL . 'assets/ee-cpt-autosave.js', array('ee-serialize-full-array', 'event_editor_js'), EVENT_ESPRESSO_VERSION, TRUE );
274 274
         wp_enqueue_script('cpt-autosave');/**/ // todo re-enable when we start doing autosave again in 4.2
275 275
 
276
-        // filter _autosave_containers
277
-        $containers = apply_filters(
278
-            'FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
279
-            $this->_autosave_containers,
280
-            $this
281
-        );
282
-        $containers = apply_filters(
283
-            'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
284
-            $containers,
285
-            $this
286
-        );
287
-
288
-        wp_localize_script(
289
-            'event_editor_js',
290
-            'EE_AUTOSAVE_IDS',
291
-            $containers
292
-        ); // todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
293
-
294
-        $unsaved_data_msg = [
295
-            'eventmsg'     => sprintf(
296
-                wp_strip_all_tags(
297
-                    __(
298
-                        "The changes you made to this %s will be lost if you navigate away from this page.",
299
-                        'event_espresso'
300
-                    )
301
-                ),
302
-                $this->_cpt_object->labels->singular_name
303
-            ),
304
-            'inputChanged' => 0,
305
-        ];
306
-        wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
307
-    }
308
-
309
-
310
-    /**
311
-     * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
312
-     *
313
-     * @return void
314
-     * @throws EE_Error
315
-     * @throws ReflectionException
316
-     * @throws Throwable
317
-     */
318
-    protected function _load_page_dependencies()
319
-    {
320
-        // we only add stuff if this is a cpt_route!
321
-        if (! $this->_cpt_route) {
322
-            parent::_load_page_dependencies();
323
-            return;
324
-        }
325
-        // now let's do some automatic filters into the wp_system
326
-        // and we'll check to make sure the CHILD class
327
-        // automatically has the required methods in place.
328
-        // the following filters are for setting all the redirects
329
-        // on DEFAULT WP custom post type actions
330
-        // let's add a hidden input to the post-edit form
331
-        // so we know when we have to trigger our custom redirects!
332
-        // Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
333
-        add_action('edit_form_after_title', [$this, 'cpt_post_form_hidden_input']);
334
-        // inject our Admin page nav tabs...
335
-        // let's make sure the nav tabs are set if they aren't already
336
-        // if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
337
-        add_action('edit_form_top', [$this, 'inject_nav_tabs']);
338
-        // modify the post_updated messages array
339
-        add_action('post_updated_messages', [$this, 'post_update_messages']);
340
-        // This basically allows us to change the title of the "publish" metabox area
341
-        // on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
342
-        $screen = $this->_cpt_routes[ $this->_req_action ];
343
-        if (! empty($this->_labels['publishbox'])) {
344
-            $this->addMetaBox(
345
-                'submitdiv',
346
-                $this->getPublishBoxTitle(),
347
-                'post_submit_meta_box',
348
-                $screen,
349
-                'side',
350
-                'core'
351
-            );
352
-        }
353
-        // let's add page_templates metabox if this cpt added support for it.
354
-        if ($this->_supports_page_templates($this->_cpt_object->name)) {
355
-            $this->addMetaBox(
356
-                'page_templates',
357
-                esc_html__('Page Template', 'event_espresso'),
358
-                [$this, 'page_template_meta_box'],
359
-                $screen,
360
-                'side'
361
-            );
362
-        }
363
-        // add preview button
364
-        // add_filter('get_sample_permalink_html', [PreviewButton::class, 'addButton'], 5, 2);
365
-        PreviewButton::addEventEditorPermalinkButton(5);
366
-        // add shortlink button to cpt edit screens.
367
-        //  We can do this as a universal thing BECAUSE, cpts use the same format for shortlinks as posts!
368
-        // add_filter('get_sample_permalink_html', [EventShortlinkButton::class, 'addButton'], 10, 2);
369
-        EventShortlinkButton::addEventEditorPermalinkButton();
370
-        // this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
371
-        // add_filter('get_sample_permalink_html', [TicketSelectorShortcodeButton::class, 'addButton'], 12, 2);
372
-        TicketSelectorShortcodeButton::addEventEditorPermalinkButton(12);
373
-        // insert our own post_stati dropdown
374
-        add_action('post_submitbox_misc_actions', [$this, 'custom_post_stati_dropdown']);
375
-        // This allows adding additional information to the publish post submitbox on the wp post edit form
376
-        if (method_exists($this, 'extra_misc_actions_publish_box')) {
377
-            add_action('post_submitbox_misc_actions', [$this, 'extra_misc_actions_publish_box']);
378
-        }
379
-        // This allows for adding additional stuff after the title field on the wp post edit form.
380
-        // This is also before the wp_editor for post description field.
381
-        if (method_exists($this, 'edit_form_after_title')) {
382
-            add_action('edit_form_after_title', [$this, 'edit_form_after_title']);
383
-        }
384
-        /**
385
-         * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
386
-         */
387
-        add_filter('clean_url', [$this, 'switch_core_wp_urls_with_ours']);
388
-        parent::_load_page_dependencies();
389
-        // notice we are ALSO going to load the pagenow hook set for this route
390
-        // (see _before_page_setup for the reset of the pagenow global ).
391
-        // This is for any plugins that are doing things properly
392
-        // and hooking into the load page hook for core wp cpt routes.
393
-        global $pagenow;
394
-        add_action('load-' . $pagenow, [$this, 'modify_current_screen'], 20);
395
-        do_action('load-' . $pagenow);
396
-        add_action('admin_enqueue_scripts', [$this, 'setup_autosave_hooks'], 30);
397
-        // we route REALLY early.
398
-        try {
399
-            $this->_route_admin_request();
400
-        } catch (EE_Error $e) {
401
-            $e->get_error();
402
-        }
403
-    }
404
-
405
-
406
-    /**
407
-     * Since we don't want users going to default core wp routes, this will check any wp urls run through the
408
-     * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
409
-     * route instead.
410
-     *
411
-     * @param string $good_protocol_url The escaped url.
412
-     * @return string possibly a new url for our route.
413
-     */
414
-    public function switch_core_wp_urls_with_ours(string $good_protocol_url): string
415
-    {
416
-        $routes_to_match = [
417
-            0 => [
418
-                'edit.php?post_type=espresso_attendees',
419
-                'admin.php?page=espresso_registrations&action=contact_list',
420
-            ],
421
-            1 => [
422
-                'edit.php?post_type=' . $this->_cpt_object->name,
423
-                'admin.php?page=' . $this->_cpt_object->name,
424
-            ],
425
-        ];
426
-        foreach ($routes_to_match as $route_matches) {
427
-            if (strpos($good_protocol_url, $route_matches[0]) !== false) {
428
-                return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
429
-            }
430
-        }
431
-        return $good_protocol_url;
432
-    }
433
-
434
-
435
-    /**
436
-     * Determine whether the current cpt supports page templates or not.
437
-     *
438
-     * @param string $cpt_name The cpt slug we're checking on.
439
-     * @return bool True supported, false not.
440
-     * @throws InvalidArgumentException
441
-     * @throws InvalidDataTypeException
442
-     * @throws InvalidInterfaceException
443
-     */
444
-    private function _supports_page_templates(string $cpt_name): bool
445
-    {
446
-        /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
447
-        $custom_post_types = $this->loader->getShared(
448
-            'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
449
-        );
450
-        $cpt_args          = $custom_post_types->getDefinitions();
451
-        $cpt_args          = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : [];
452
-        $cpt_has_support   = ! empty($cpt_args['page_templates']);
453
-
454
-        $post_templates = wp_get_theme()->get_post_templates();
455
-        // if there are $post_templates for this cpt, then we return false for this method because
456
-        // that means we aren't going to load our page template manager and leave that up to the native
457
-        // cpt template manager.
458
-        return ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
459
-    }
460
-
461
-
462
-    /**
463
-     * Callback for the page_templates metabox selector.
464
-     *
465
-     * @return void
466
-     */
467
-    public function page_template_meta_box()
468
-    {
469
-        global $post;
470
-        $template = '';
471
-
472
-        $page_template_count = count(get_page_templates());
473
-        if ($page_template_count) {
474
-            $page_template = get_post_meta($post->ID, '_wp_page_template', true);
475
-            $template      = ! empty($page_template) ? $page_template : '';
476
-        }
477
-        ?>
276
+		// filter _autosave_containers
277
+		$containers = apply_filters(
278
+			'FHEE__EE_Admin_Page_CPT___load_autosave_scripts_styles__containers',
279
+			$this->_autosave_containers,
280
+			$this
281
+		);
282
+		$containers = apply_filters(
283
+			'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
284
+			$containers,
285
+			$this
286
+		);
287
+
288
+		wp_localize_script(
289
+			'event_editor_js',
290
+			'EE_AUTOSAVE_IDS',
291
+			$containers
292
+		); // todo once we enable autosaves, this needs to be switched to localize with "cpt-autosave"
293
+
294
+		$unsaved_data_msg = [
295
+			'eventmsg'     => sprintf(
296
+				wp_strip_all_tags(
297
+					__(
298
+						"The changes you made to this %s will be lost if you navigate away from this page.",
299
+						'event_espresso'
300
+					)
301
+				),
302
+				$this->_cpt_object->labels->singular_name
303
+			),
304
+			'inputChanged' => 0,
305
+		];
306
+		wp_localize_script('event_editor_js', 'UNSAVED_DATA_MSG', $unsaved_data_msg);
307
+	}
308
+
309
+
310
+	/**
311
+	 * overloading the EE_Admin_Page parent load_page_dependencies so we can get the cpt stuff added in appropriately
312
+	 *
313
+	 * @return void
314
+	 * @throws EE_Error
315
+	 * @throws ReflectionException
316
+	 * @throws Throwable
317
+	 */
318
+	protected function _load_page_dependencies()
319
+	{
320
+		// we only add stuff if this is a cpt_route!
321
+		if (! $this->_cpt_route) {
322
+			parent::_load_page_dependencies();
323
+			return;
324
+		}
325
+		// now let's do some automatic filters into the wp_system
326
+		// and we'll check to make sure the CHILD class
327
+		// automatically has the required methods in place.
328
+		// the following filters are for setting all the redirects
329
+		// on DEFAULT WP custom post type actions
330
+		// let's add a hidden input to the post-edit form
331
+		// so we know when we have to trigger our custom redirects!
332
+		// Otherwise the redirects will happen on ALL post saves which wouldn't be good of course!
333
+		add_action('edit_form_after_title', [$this, 'cpt_post_form_hidden_input']);
334
+		// inject our Admin page nav tabs...
335
+		// let's make sure the nav tabs are set if they aren't already
336
+		// if ( empty( $this->_nav_tabs ) ) $this->_set_nav_tabs();
337
+		add_action('edit_form_top', [$this, 'inject_nav_tabs']);
338
+		// modify the post_updated messages array
339
+		add_action('post_updated_messages', [$this, 'post_update_messages']);
340
+		// This basically allows us to change the title of the "publish" metabox area
341
+		// on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
342
+		$screen = $this->_cpt_routes[ $this->_req_action ];
343
+		if (! empty($this->_labels['publishbox'])) {
344
+			$this->addMetaBox(
345
+				'submitdiv',
346
+				$this->getPublishBoxTitle(),
347
+				'post_submit_meta_box',
348
+				$screen,
349
+				'side',
350
+				'core'
351
+			);
352
+		}
353
+		// let's add page_templates metabox if this cpt added support for it.
354
+		if ($this->_supports_page_templates($this->_cpt_object->name)) {
355
+			$this->addMetaBox(
356
+				'page_templates',
357
+				esc_html__('Page Template', 'event_espresso'),
358
+				[$this, 'page_template_meta_box'],
359
+				$screen,
360
+				'side'
361
+			);
362
+		}
363
+		// add preview button
364
+		// add_filter('get_sample_permalink_html', [PreviewButton::class, 'addButton'], 5, 2);
365
+		PreviewButton::addEventEditorPermalinkButton(5);
366
+		// add shortlink button to cpt edit screens.
367
+		//  We can do this as a universal thing BECAUSE, cpts use the same format for shortlinks as posts!
368
+		// add_filter('get_sample_permalink_html', [EventShortlinkButton::class, 'addButton'], 10, 2);
369
+		EventShortlinkButton::addEventEditorPermalinkButton();
370
+		// this is a filter that allows the addition of extra html after the permalink field on the wp post edit-form
371
+		// add_filter('get_sample_permalink_html', [TicketSelectorShortcodeButton::class, 'addButton'], 12, 2);
372
+		TicketSelectorShortcodeButton::addEventEditorPermalinkButton(12);
373
+		// insert our own post_stati dropdown
374
+		add_action('post_submitbox_misc_actions', [$this, 'custom_post_stati_dropdown']);
375
+		// This allows adding additional information to the publish post submitbox on the wp post edit form
376
+		if (method_exists($this, 'extra_misc_actions_publish_box')) {
377
+			add_action('post_submitbox_misc_actions', [$this, 'extra_misc_actions_publish_box']);
378
+		}
379
+		// This allows for adding additional stuff after the title field on the wp post edit form.
380
+		// This is also before the wp_editor for post description field.
381
+		if (method_exists($this, 'edit_form_after_title')) {
382
+			add_action('edit_form_after_title', [$this, 'edit_form_after_title']);
383
+		}
384
+		/**
385
+		 * Filtering WP's esc_url to capture urls pointing to core wp routes so they point to our route.
386
+		 */
387
+		add_filter('clean_url', [$this, 'switch_core_wp_urls_with_ours']);
388
+		parent::_load_page_dependencies();
389
+		// notice we are ALSO going to load the pagenow hook set for this route
390
+		// (see _before_page_setup for the reset of the pagenow global ).
391
+		// This is for any plugins that are doing things properly
392
+		// and hooking into the load page hook for core wp cpt routes.
393
+		global $pagenow;
394
+		add_action('load-' . $pagenow, [$this, 'modify_current_screen'], 20);
395
+		do_action('load-' . $pagenow);
396
+		add_action('admin_enqueue_scripts', [$this, 'setup_autosave_hooks'], 30);
397
+		// we route REALLY early.
398
+		try {
399
+			$this->_route_admin_request();
400
+		} catch (EE_Error $e) {
401
+			$e->get_error();
402
+		}
403
+	}
404
+
405
+
406
+	/**
407
+	 * Since we don't want users going to default core wp routes, this will check any wp urls run through the
408
+	 * esc_url() method and if we see a url matching a pattern for our routes, we'll modify it to point to OUR
409
+	 * route instead.
410
+	 *
411
+	 * @param string $good_protocol_url The escaped url.
412
+	 * @return string possibly a new url for our route.
413
+	 */
414
+	public function switch_core_wp_urls_with_ours(string $good_protocol_url): string
415
+	{
416
+		$routes_to_match = [
417
+			0 => [
418
+				'edit.php?post_type=espresso_attendees',
419
+				'admin.php?page=espresso_registrations&action=contact_list',
420
+			],
421
+			1 => [
422
+				'edit.php?post_type=' . $this->_cpt_object->name,
423
+				'admin.php?page=' . $this->_cpt_object->name,
424
+			],
425
+		];
426
+		foreach ($routes_to_match as $route_matches) {
427
+			if (strpos($good_protocol_url, $route_matches[0]) !== false) {
428
+				return str_replace($route_matches[0], $route_matches[1], $good_protocol_url);
429
+			}
430
+		}
431
+		return $good_protocol_url;
432
+	}
433
+
434
+
435
+	/**
436
+	 * Determine whether the current cpt supports page templates or not.
437
+	 *
438
+	 * @param string $cpt_name The cpt slug we're checking on.
439
+	 * @return bool True supported, false not.
440
+	 * @throws InvalidArgumentException
441
+	 * @throws InvalidDataTypeException
442
+	 * @throws InvalidInterfaceException
443
+	 */
444
+	private function _supports_page_templates(string $cpt_name): bool
445
+	{
446
+		/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
447
+		$custom_post_types = $this->loader->getShared(
448
+			'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
449
+		);
450
+		$cpt_args          = $custom_post_types->getDefinitions();
451
+		$cpt_args          = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : [];
452
+		$cpt_has_support   = ! empty($cpt_args['page_templates']);
453
+
454
+		$post_templates = wp_get_theme()->get_post_templates();
455
+		// if there are $post_templates for this cpt, then we return false for this method because
456
+		// that means we aren't going to load our page template manager and leave that up to the native
457
+		// cpt template manager.
458
+		return ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
459
+	}
460
+
461
+
462
+	/**
463
+	 * Callback for the page_templates metabox selector.
464
+	 *
465
+	 * @return void
466
+	 */
467
+	public function page_template_meta_box()
468
+	{
469
+		global $post;
470
+		$template = '';
471
+
472
+		$page_template_count = count(get_page_templates());
473
+		if ($page_template_count) {
474
+			$page_template = get_post_meta($post->ID, '_wp_page_template', true);
475
+			$template      = ! empty($page_template) ? $page_template : '';
476
+		}
477
+		?>
478 478
         <p><strong><?php esc_html_e('Template', 'event_espresso') ?></strong></p>
479 479
         <label class="screen-reader-text" for="page_template">
480 480
             <?php esc_html_e('Page Template', 'event_espresso') ?>
@@ -484,457 +484,457 @@  discard block
 block discarded – undo
484 484
             <?php page_template_dropdown($template); ?>
485 485
         </select>
486 486
         <?php
487
-    }
488
-
489
-
490
-    /**
491
-     * if this post is a draft or scheduled post then we provide a preview button for user to click
492
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
493
-     *
494
-     * @param string $return    the current html
495
-     * @param int    $id        the post id for the page
496
-     * @return string            The new html string for the permalink area
497
-     * @deprecated 5.0.0.p
498
-     * @see PreviewButton::addButton()
499
-     */
500
-    public function preview_button_html(string $return, int $id): string
501
-    {
502
-        return PreviewButton::addButton($return, $id);
503
-    }
504
-
505
-
506
-    /**
507
-     * add our custom post status dropdown on the wp post page for this cpt
508
-     *
509
-     * @return void
510
-     */
511
-    public function custom_post_stati_dropdown()
512
-    {
513
-        $statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
514
-        $cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
515
-            ? $statuses[ $this->_cpt_model_obj->status() ]
516
-            : '';
517
-        $template_args    = [
518
-            'cur_status'            => $this->_cpt_model_obj->status(),
519
-            'statuses'              => $statuses,
520
-            'cur_status_label'      => $cur_status_label,
521
-            'localized_status_save' => sprintf(esc_html__('Save %s', 'event_espresso'), $cur_status_label),
522
-        ];
523
-        // we'll add a trash post status (WP doesn't add one for some reason)
524
-        if ($this->_cpt_model_obj->status() === 'trash') {
525
-            $template_args['cur_status_label'] = esc_html__('Trashed', 'event_espresso');
526
-            $statuses['trash']                 = esc_html__('Trashed', 'event_espresso');
527
-            $template_args['statuses']         = $statuses;
528
-        }
529
-
530
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
531
-        EEH_Template::display_template($template, $template_args);
532
-    }
533
-
534
-
535
-    public function setup_autosave_hooks()
536
-    {
537
-        $this->_set_autosave_containers();
538
-        $this->_load_autosave_scripts_styles();
539
-    }
540
-
541
-
542
-    /**
543
-     * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a post object (available
544
-     * in request data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
545
-     * for the nonce in here, but then this method looks for two things:
546
-     * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
547
-     * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
548
-     * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
549
-     * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
550
-     * template args.
551
-     *    1. $template_args['error'] = IF there is an error you can add the message in here.
552
-     *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
553
-     *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
554
-     *    $this->_template_args['data']['items'] = array(
555
-     *        'event-datetime-ids' => '1,2,3';
556
-     *    );
557
-     *    Keep in mind the following things:
558
-     *    - "where" index is for the input with the id as that string.
559
-     *    - "what" index is what will be used for the value of that input.
560
-     *
561
-     * @return void
562
-     * @throws EE_Error
563
-     */
564
-    public function do_extra_autosave_stuff()
565
-    {
566
-        // next let's check for the autosave nonce (we'll use _verify_nonce )
567
-        $nonce = $this->request->getRequestParam('autosavenonce');
568
-        $this->_verify_nonce($nonce, 'autosave');
569
-        // make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
570
-        if (! defined('DOING_AUTOSAVE')) {
571
-            define('DOING_AUTOSAVE', true);
572
-        }
573
-        // if we made it here then the nonce checked out.  Let's run our methods and actions
574
-        $autosave = "_ee_autosave_$this->_current_view";
575
-        if (method_exists($this, $autosave)) {
576
-            $this->$autosave();
577
-        } else {
578
-            $this->_template_args['success'] = true;
579
-        }
580
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
581
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
582
-        // now let's return json
583
-        $this->_return_json();
584
-    }
585
-
586
-
587
-    /**
588
-     * This takes care of setting up default routes and pages that utilize the core WP admin pages.
589
-     * Child classes can override the defaults (in cases for adding metaboxes etc.)
590
-     * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
591
-     *
592
-     * @return void
593
-     * @throws EE_Error
594
-     * @throws ReflectionException
595
-     */
596
-    protected function _extend_page_config_for_cpt()
597
-    {
598
-        // before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
599
-        if ($this->raw_req_page !== $this->page_slug) {
600
-            return;
601
-        }
602
-        // set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
603
-        if (! empty($this->_cpt_object)) {
604
-            $this->_page_routes = array_merge(
605
-                [
606
-                    'create_new' => [$this, '_create_new_cpt_item'],
607
-                    'edit'       => [$this, '_edit_cpt_item'],
608
-                ],
609
-                $this->_page_routes
610
-            );
611
-            $this->_page_config = array_merge(
612
-                [
613
-                    'create_new' => [
614
-                        'nav'           => [
615
-                            'label' => $this->_cpt_object->labels->add_new_item,
616
-                            'order' => 5,
617
-                        ],
618
-                        'require_nonce' => false,
619
-                    ],
620
-                    'edit'       => [
621
-                        'nav'           => [
622
-                            'label'      => $this->_cpt_object->labels->edit_item,
623
-                            'order'      => 5,
624
-                            'persistent' => false,
625
-                            'url'        => '',
626
-                        ],
627
-                        'require_nonce' => false,
628
-                    ],
629
-                ],
630
-                $this->_page_config
631
-            );
632
-        }
633
-        // load the next section only if this is a matching cpt route as set in the cpt routes array.
634
-        if (! isset($this->_cpt_routes[ $this->_req_action ])) {
635
-            return;
636
-        }
637
-        $this->_cpt_route = true;
638
-        // $this->_cpt_route = isset($this->_cpt_routes[ $this->_req_action ]);
639
-        // add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
640
-        if (empty($this->_cpt_object)) {
641
-            $msg = sprintf(
642
-                esc_html__(
643
-                    'This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).',
644
-                    'event_espresso'
645
-                ),
646
-                $this->page_slug,
647
-                $this->_req_action,
648
-                get_class($this)
649
-            );
650
-            throw new EE_Error($msg);
651
-        }
652
-        $this->_set_model_object($this->request->getRequestParam('post', 0, DataType::INT));
653
-    }
654
-
655
-
656
-    /**
657
-     * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
658
-     *
659
-     * @param int    $id       The id to retrieve the model object for. If empty we set a default object.
660
-     * @param bool   $ignore_route_check
661
-     * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
662
-     * @throws EE_Error
663
-     * @throws InvalidArgumentException
664
-     * @throws InvalidDataTypeException
665
-     * @throws InvalidInterfaceException
666
-     * @throws ReflectionException
667
-     */
668
-    protected function _set_model_object(int $id = 0, bool $ignore_route_check = false, string $req_type = '')
669
-    {
670
-        $model = null;
671
-        if (
672
-            empty($this->_cpt_model_names)
673
-            || (
674
-                ! $ignore_route_check
675
-                && ! isset($this->_cpt_routes[ $this->_req_action ])
676
-            )
677
-            || (
678
-                $this->_cpt_model_obj instanceof EE_CPT_Base
679
-                && $this->_cpt_model_obj->ID() === $id
680
-            )
681
-        ) {
682
-            // get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
683
-            return;
684
-        }
685
-        // if ignore_route_check is true, then get the model name via CustomPostTypeDefinitions
686
-        if ($ignore_route_check) {
687
-            $post_type = get_post_type($id);
688
-            /** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
689
-            $custom_post_types = $this->loader->getShared(
690
-                'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
691
-            );
692
-            $model_names       = $custom_post_types->getCustomPostTypeModelNames($post_type);
693
-            if (isset($model_names[ $post_type ])) {
694
-                $model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
695
-            }
696
-        } else {
697
-            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
698
-        }
699
-        if ($model instanceof EEM_Base) {
700
-            $this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
701
-        }
702
-        do_action(
703
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
704
-            $this->_cpt_model_obj,
705
-            $req_type
706
-        );
707
-    }
708
-
709
-
710
-    /**
711
-     * admin_init_global
712
-     * This runs all the code that we want executed within the WP admin_init hook.
713
-     * This method executes for ALL EE Admin pages.
714
-     *
715
-     * @return void
716
-     */
717
-    public function admin_init_global()
718
-    {
719
-        $post_ID = $this->request->getRequestParam('post', 0, DataType::INT);
720
-        // its possible this is a new save so let's catch that instead
721
-        $post_ID        = $this->request->getRequestParam('post_ID', $post_ID, DataType::INT);
722
-        $post           = get_post($post_ID);
723
-        $post_type      = $post instanceof WP_Post ? $post->post_type : false;
724
-        $current_route  = $this->request->getRequestParam('current_route', 'shouldneverwork');
725
-        $route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
726
-            ? $this->_cpt_routes[ $current_route ]
727
-            : '';
728
-        add_filter('get_delete_post_link', [$this, 'modify_delete_post_link'], 10, 2);
729
-        add_filter('get_edit_post_link', [$this, 'modify_edit_post_link'], 10, 2);
730
-        if ($post_type === $route_to_check) {
731
-            add_filter('redirect_post_location', [$this, 'cpt_post_location_redirect'], 10, 2);
732
-        }
733
-        // now let's filter redirect if we're on a revision page and the revision is for an event CPT.
734
-        $revision = $this->request->getRequestParam('revision');
735
-        if (! empty($revision)) {
736
-            $action = $this->request->getRequestParam('action');
737
-            // doing a restore?
738
-            if (! empty($action) && $action === 'restore') {
739
-                // get post for revision
740
-                $rev_post   = get_post($revision);
741
-                $rev_parent = get_post($rev_post->post_parent);
742
-                // only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
743
-                if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
744
-                    add_filter('wp_redirect', [$this, 'revision_redirect']);
745
-                    // restores of revisions
746
-                    add_action('wp_restore_post_revision', [$this, 'restore_revision'], 10, 2);
747
-                }
748
-            }
749
-        }
750
-        // NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
751
-        if ($post_type && $post_type === $route_to_check) {
752
-            // $post_id, $post
753
-            add_action('save_post', [$this, 'insert_update'], 10, 3);
754
-            // $post_id
755
-            add_action('trashed_post', [$this, 'before_trash_cpt_item']);
756
-            add_action('trashed_post', [$this, 'dont_permanently_delete_ee_cpts']);
757
-            add_action('untrashed_post', [$this, 'before_restore_cpt_item']);
758
-            add_action('after_delete_post', [$this, 'before_delete_cpt_item']);
759
-        }
760
-    }
761
-
762
-
763
-    /**
764
-     * Callback for the WordPress trashed_post hook.
765
-     * Execute some basic checks before calling the trash_cpt_item declared in the child class.
766
-     *
767
-     * @param int $post_id
768
-     * @throws EE_Error
769
-     * @throws ReflectionException
770
-     */
771
-    public function before_trash_cpt_item(int $post_id)
772
-    {
773
-        $this->_set_model_object($post_id, true, 'trash');
774
-        // if our cpt object isn't existent then get out immediately.
775
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
776
-            return;
777
-        }
778
-        $this->trash_cpt_item($post_id);
779
-    }
780
-
781
-
782
-    /**
783
-     * Callback for the WordPress untrashed_post hook.
784
-     * Execute some basic checks before calling the restore_cpt_method in the child class.
785
-     *
786
-     * @param $post_id
787
-     * @throws EE_Error
788
-     * @throws ReflectionException
789
-     */
790
-    public function before_restore_cpt_item($post_id)
791
-    {
792
-        $this->_set_model_object($post_id, true, 'restore');
793
-        // if our cpt object isn't existent then get out immediately.
794
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
795
-            return;
796
-        }
797
-        $this->restore_cpt_item($post_id);
798
-    }
799
-
800
-
801
-    /**
802
-     * Callback for the WordPress after_delete_post hook.
803
-     * Execute some basic checks before calling the delete_cpt_item method in the child class.
804
-     *
805
-     * @param $post_id
806
-     * @throws EE_Error
807
-     * @throws ReflectionException
808
-     */
809
-    public function before_delete_cpt_item($post_id)
810
-    {
811
-        $this->_set_model_object($post_id, true, 'delete');
812
-        // if our cpt object isn't existent then get out immediately.
813
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
814
-            return;
815
-        }
816
-        $this->delete_cpt_item($post_id);
817
-    }
818
-
819
-
820
-    /**
821
-     * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
822
-     * accordingly.
823
-     *
824
-     * @return void
825
-     * @throws EE_Error
826
-     * @throws ReflectionException
827
-     */
828
-    public function verify_cpt_object()
829
-    {
830
-        $label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
831
-        // verify event object
832
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
833
-            throw new EE_Error(
834
-                sprintf(
835
-                    esc_html__(
836
-                        'Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
837
-                        'event_espresso'
838
-                    ),
839
-                    $label
840
-                )
841
-            );
842
-        }
843
-        // if auto-draft then throw an error
844
-        if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
845
-            EE_Error::overwrite_errors();
846
-            EE_Error::add_error(
847
-                sprintf(
848
-                    esc_html__(
849
-                        'This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.',
850
-                        'event_espresso'
851
-                    ),
852
-                    $label
853
-                ),
854
-                __FILE__,
855
-                __FUNCTION__,
856
-                __LINE__
857
-            );
858
-        }
859
-    }
860
-
861
-
862
-    /**
863
-     * admin_footer_scripts_global
864
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
865
-     * will apply on ALL EE_Admin pages.
866
-     *
867
-     * @return void
868
-     */
869
-    public function admin_footer_scripts_global()
870
-    {
871
-        $this->_add_admin_page_ajax_loading_img();
872
-        $this->_add_admin_page_overlay();
873
-    }
874
-
875
-
876
-    /**
877
-     * add in any global scripts for cpt routes
878
-     *
879
-     * @return void
880
-     */
881
-    public function load_global_scripts_styles()
882
-    {
883
-        parent::load_global_scripts_styles();
884
-        if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
885
-            // setup custom post status object for localize script but only if we've got a cpt object
886
-            $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
887
-            if (! empty($statuses)) {
888
-                // get ALL statuses!
889
-                $statuses = $this->_cpt_model_obj->get_all_post_statuses();
890
-                // setup object
891
-                $ee_cpt_statuses = [];
892
-                foreach ($statuses as $status => $label) {
893
-                    $ee_cpt_statuses[ $status ] = [
894
-                        'label'      => $label,
895
-                        'save_label' => sprintf(
896
-                            wp_strip_all_tags(__('Save as %s', 'event_espresso')),
897
-                            $label
898
-                        ),
899
-                    ];
900
-                }
901
-                wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
902
-            }
903
-        }
904
-    }
905
-
906
-
907
-    /**
908
-     * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
909
-     * insert/updates
910
-     *
911
-     * @param int     $post_id ID of post being updated
912
-     * @param WP_Post $post    Post object from WP
913
-     * @param bool    $update  Whether this is an update or a new save.
914
-     * @return void
915
-     * @throws EE_Error
916
-     * @throws ReflectionException
917
-     */
918
-    public function insert_update(int $post_id, WP_Post $post, bool $update)
919
-    {
920
-        // make sure that if this is a revision OR trash action that we don't do any updates!
921
-        $action = $this->request->getRequestParam('action');
922
-        if ($action === 'restore' || $action === 'trash') {
923
-            return;
924
-        }
925
-        $this->_set_model_object($post_id, true, 'insert_update');
926
-        // if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
927
-        if (
928
-            $update
929
-            && (
930
-                ! $this->_cpt_model_obj instanceof EE_CPT_Base
931
-                || $this->_cpt_model_obj->ID() !== $post_id
932
-            )
933
-        ) {
934
-            return;
935
-        }
936
-        // check for autosave and update our req_data property accordingly.
937
-        /*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
487
+	}
488
+
489
+
490
+	/**
491
+	 * if this post is a draft or scheduled post then we provide a preview button for user to click
492
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
493
+	 *
494
+	 * @param string $return    the current html
495
+	 * @param int    $id        the post id for the page
496
+	 * @return string            The new html string for the permalink area
497
+	 * @deprecated 5.0.0.p
498
+	 * @see PreviewButton::addButton()
499
+	 */
500
+	public function preview_button_html(string $return, int $id): string
501
+	{
502
+		return PreviewButton::addButton($return, $id);
503
+	}
504
+
505
+
506
+	/**
507
+	 * add our custom post status dropdown on the wp post page for this cpt
508
+	 *
509
+	 * @return void
510
+	 */
511
+	public function custom_post_stati_dropdown()
512
+	{
513
+		$statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
514
+		$cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
515
+			? $statuses[ $this->_cpt_model_obj->status() ]
516
+			: '';
517
+		$template_args    = [
518
+			'cur_status'            => $this->_cpt_model_obj->status(),
519
+			'statuses'              => $statuses,
520
+			'cur_status_label'      => $cur_status_label,
521
+			'localized_status_save' => sprintf(esc_html__('Save %s', 'event_espresso'), $cur_status_label),
522
+		];
523
+		// we'll add a trash post status (WP doesn't add one for some reason)
524
+		if ($this->_cpt_model_obj->status() === 'trash') {
525
+			$template_args['cur_status_label'] = esc_html__('Trashed', 'event_espresso');
526
+			$statuses['trash']                 = esc_html__('Trashed', 'event_espresso');
527
+			$template_args['statuses']         = $statuses;
528
+		}
529
+
530
+		$template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
531
+		EEH_Template::display_template($template, $template_args);
532
+	}
533
+
534
+
535
+	public function setup_autosave_hooks()
536
+	{
537
+		$this->_set_autosave_containers();
538
+		$this->_load_autosave_scripts_styles();
539
+	}
540
+
541
+
542
+	/**
543
+	 * This is run on all WordPress autosaves AFTER the autosave is complete and sends along a post object (available
544
+	 * in request data) containing: post_ID of the saved post autosavenonce for the saved post We'll do the check
545
+	 * for the nonce in here, but then this method looks for two things:
546
+	 * 1. Execute a method (if exists) matching 'ee_autosave_' and appended with the given route. OR
547
+	 * 2. do_actions() for global or class specific actions that have been registered (for plugins/addons not in an
548
+	 * EE_Admin_Page class. PLEASE NOTE: Data will be returned using the _return_json() object and so the
549
+	 * $_template_args property should be used to hold the $data array.  We're expecting the following things set in
550
+	 * template args.
551
+	 *    1. $template_args['error'] = IF there is an error you can add the message in here.
552
+	 *    2. $template_args['data']['items'] = an array of items that are setup in key index pairs of 'where_values_go'
553
+	 *    => 'values_to_add'.  In other words, for the datetime metabox we'll have something like
554
+	 *    $this->_template_args['data']['items'] = array(
555
+	 *        'event-datetime-ids' => '1,2,3';
556
+	 *    );
557
+	 *    Keep in mind the following things:
558
+	 *    - "where" index is for the input with the id as that string.
559
+	 *    - "what" index is what will be used for the value of that input.
560
+	 *
561
+	 * @return void
562
+	 * @throws EE_Error
563
+	 */
564
+	public function do_extra_autosave_stuff()
565
+	{
566
+		// next let's check for the autosave nonce (we'll use _verify_nonce )
567
+		$nonce = $this->request->getRequestParam('autosavenonce');
568
+		$this->_verify_nonce($nonce, 'autosave');
569
+		// make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
570
+		if (! defined('DOING_AUTOSAVE')) {
571
+			define('DOING_AUTOSAVE', true);
572
+		}
573
+		// if we made it here then the nonce checked out.  Let's run our methods and actions
574
+		$autosave = "_ee_autosave_$this->_current_view";
575
+		if (method_exists($this, $autosave)) {
576
+			$this->$autosave();
577
+		} else {
578
+			$this->_template_args['success'] = true;
579
+		}
580
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
581
+		do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
582
+		// now let's return json
583
+		$this->_return_json();
584
+	}
585
+
586
+
587
+	/**
588
+	 * This takes care of setting up default routes and pages that utilize the core WP admin pages.
589
+	 * Child classes can override the defaults (in cases for adding metaboxes etc.)
590
+	 * but take care that you include the defaults here otherwise your core WP admin pages for the cpt won't work!
591
+	 *
592
+	 * @return void
593
+	 * @throws EE_Error
594
+	 * @throws ReflectionException
595
+	 */
596
+	protected function _extend_page_config_for_cpt()
597
+	{
598
+		// before doing anything we need to make sure this runs ONLY when the loaded page matches the set page_slug
599
+		if ($this->raw_req_page !== $this->page_slug) {
600
+			return;
601
+		}
602
+		// set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
603
+		if (! empty($this->_cpt_object)) {
604
+			$this->_page_routes = array_merge(
605
+				[
606
+					'create_new' => [$this, '_create_new_cpt_item'],
607
+					'edit'       => [$this, '_edit_cpt_item'],
608
+				],
609
+				$this->_page_routes
610
+			);
611
+			$this->_page_config = array_merge(
612
+				[
613
+					'create_new' => [
614
+						'nav'           => [
615
+							'label' => $this->_cpt_object->labels->add_new_item,
616
+							'order' => 5,
617
+						],
618
+						'require_nonce' => false,
619
+					],
620
+					'edit'       => [
621
+						'nav'           => [
622
+							'label'      => $this->_cpt_object->labels->edit_item,
623
+							'order'      => 5,
624
+							'persistent' => false,
625
+							'url'        => '',
626
+						],
627
+						'require_nonce' => false,
628
+					],
629
+				],
630
+				$this->_page_config
631
+			);
632
+		}
633
+		// load the next section only if this is a matching cpt route as set in the cpt routes array.
634
+		if (! isset($this->_cpt_routes[ $this->_req_action ])) {
635
+			return;
636
+		}
637
+		$this->_cpt_route = true;
638
+		// $this->_cpt_route = isset($this->_cpt_routes[ $this->_req_action ]);
639
+		// add_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', array( $this, 'modify_current_screen') );
640
+		if (empty($this->_cpt_object)) {
641
+			$msg = sprintf(
642
+				esc_html__(
643
+					'This page has been set as being related to a registered custom post type, however, the custom post type object could not be retrieved. There are two possible reasons for this:  1. The "%s" does not match a registered post type. or 2. The custom post type is not registered for the "%s" action as indexed in the "$_cpt_routes" property on this class (%s).',
644
+					'event_espresso'
645
+				),
646
+				$this->page_slug,
647
+				$this->_req_action,
648
+				get_class($this)
649
+			);
650
+			throw new EE_Error($msg);
651
+		}
652
+		$this->_set_model_object($this->request->getRequestParam('post', 0, DataType::INT));
653
+	}
654
+
655
+
656
+	/**
657
+	 * Sets the _cpt_model_object property using what has been set for the _cpt_model_name and a given id.
658
+	 *
659
+	 * @param int    $id       The id to retrieve the model object for. If empty we set a default object.
660
+	 * @param bool   $ignore_route_check
661
+	 * @param string $req_type whether the current route is for inserting, updating, or deleting the CPT
662
+	 * @throws EE_Error
663
+	 * @throws InvalidArgumentException
664
+	 * @throws InvalidDataTypeException
665
+	 * @throws InvalidInterfaceException
666
+	 * @throws ReflectionException
667
+	 */
668
+	protected function _set_model_object(int $id = 0, bool $ignore_route_check = false, string $req_type = '')
669
+	{
670
+		$model = null;
671
+		if (
672
+			empty($this->_cpt_model_names)
673
+			|| (
674
+				! $ignore_route_check
675
+				&& ! isset($this->_cpt_routes[ $this->_req_action ])
676
+			)
677
+			|| (
678
+				$this->_cpt_model_obj instanceof EE_CPT_Base
679
+				&& $this->_cpt_model_obj->ID() === $id
680
+			)
681
+		) {
682
+			// get out cuz we either don't have a model name OR the object has already been set and it has the same id as what has been sent.
683
+			return;
684
+		}
685
+		// if ignore_route_check is true, then get the model name via CustomPostTypeDefinitions
686
+		if ($ignore_route_check) {
687
+			$post_type = get_post_type($id);
688
+			/** @var EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions $custom_post_types */
689
+			$custom_post_types = $this->loader->getShared(
690
+				'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
691
+			);
692
+			$model_names       = $custom_post_types->getCustomPostTypeModelNames($post_type);
693
+			if (isset($model_names[ $post_type ])) {
694
+				$model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
695
+			}
696
+		} else {
697
+			$model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
698
+		}
699
+		if ($model instanceof EEM_Base) {
700
+			$this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
701
+		}
702
+		do_action(
703
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
704
+			$this->_cpt_model_obj,
705
+			$req_type
706
+		);
707
+	}
708
+
709
+
710
+	/**
711
+	 * admin_init_global
712
+	 * This runs all the code that we want executed within the WP admin_init hook.
713
+	 * This method executes for ALL EE Admin pages.
714
+	 *
715
+	 * @return void
716
+	 */
717
+	public function admin_init_global()
718
+	{
719
+		$post_ID = $this->request->getRequestParam('post', 0, DataType::INT);
720
+		// its possible this is a new save so let's catch that instead
721
+		$post_ID        = $this->request->getRequestParam('post_ID', $post_ID, DataType::INT);
722
+		$post           = get_post($post_ID);
723
+		$post_type      = $post instanceof WP_Post ? $post->post_type : false;
724
+		$current_route  = $this->request->getRequestParam('current_route', 'shouldneverwork');
725
+		$route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
726
+			? $this->_cpt_routes[ $current_route ]
727
+			: '';
728
+		add_filter('get_delete_post_link', [$this, 'modify_delete_post_link'], 10, 2);
729
+		add_filter('get_edit_post_link', [$this, 'modify_edit_post_link'], 10, 2);
730
+		if ($post_type === $route_to_check) {
731
+			add_filter('redirect_post_location', [$this, 'cpt_post_location_redirect'], 10, 2);
732
+		}
733
+		// now let's filter redirect if we're on a revision page and the revision is for an event CPT.
734
+		$revision = $this->request->getRequestParam('revision');
735
+		if (! empty($revision)) {
736
+			$action = $this->request->getRequestParam('action');
737
+			// doing a restore?
738
+			if (! empty($action) && $action === 'restore') {
739
+				// get post for revision
740
+				$rev_post   = get_post($revision);
741
+				$rev_parent = get_post($rev_post->post_parent);
742
+				// only do our redirect filter AND our restore revision action if the post_type for the parent is one of our cpts.
743
+				if ($rev_parent && $rev_parent->post_type === $this->page_slug) {
744
+					add_filter('wp_redirect', [$this, 'revision_redirect']);
745
+					// restores of revisions
746
+					add_action('wp_restore_post_revision', [$this, 'restore_revision'], 10, 2);
747
+				}
748
+			}
749
+		}
750
+		// NOTE we ONLY want to run these hooks if we're on the right class for the given post type.  Otherwise we could see some really freaky things happen!
751
+		if ($post_type && $post_type === $route_to_check) {
752
+			// $post_id, $post
753
+			add_action('save_post', [$this, 'insert_update'], 10, 3);
754
+			// $post_id
755
+			add_action('trashed_post', [$this, 'before_trash_cpt_item']);
756
+			add_action('trashed_post', [$this, 'dont_permanently_delete_ee_cpts']);
757
+			add_action('untrashed_post', [$this, 'before_restore_cpt_item']);
758
+			add_action('after_delete_post', [$this, 'before_delete_cpt_item']);
759
+		}
760
+	}
761
+
762
+
763
+	/**
764
+	 * Callback for the WordPress trashed_post hook.
765
+	 * Execute some basic checks before calling the trash_cpt_item declared in the child class.
766
+	 *
767
+	 * @param int $post_id
768
+	 * @throws EE_Error
769
+	 * @throws ReflectionException
770
+	 */
771
+	public function before_trash_cpt_item(int $post_id)
772
+	{
773
+		$this->_set_model_object($post_id, true, 'trash');
774
+		// if our cpt object isn't existent then get out immediately.
775
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
776
+			return;
777
+		}
778
+		$this->trash_cpt_item($post_id);
779
+	}
780
+
781
+
782
+	/**
783
+	 * Callback for the WordPress untrashed_post hook.
784
+	 * Execute some basic checks before calling the restore_cpt_method in the child class.
785
+	 *
786
+	 * @param $post_id
787
+	 * @throws EE_Error
788
+	 * @throws ReflectionException
789
+	 */
790
+	public function before_restore_cpt_item($post_id)
791
+	{
792
+		$this->_set_model_object($post_id, true, 'restore');
793
+		// if our cpt object isn't existent then get out immediately.
794
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
795
+			return;
796
+		}
797
+		$this->restore_cpt_item($post_id);
798
+	}
799
+
800
+
801
+	/**
802
+	 * Callback for the WordPress after_delete_post hook.
803
+	 * Execute some basic checks before calling the delete_cpt_item method in the child class.
804
+	 *
805
+	 * @param $post_id
806
+	 * @throws EE_Error
807
+	 * @throws ReflectionException
808
+	 */
809
+	public function before_delete_cpt_item($post_id)
810
+	{
811
+		$this->_set_model_object($post_id, true, 'delete');
812
+		// if our cpt object isn't existent then get out immediately.
813
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
814
+			return;
815
+		}
816
+		$this->delete_cpt_item($post_id);
817
+	}
818
+
819
+
820
+	/**
821
+	 * This simply verifies if the cpt_model_object is instantiated for the given page and throws an error message
822
+	 * accordingly.
823
+	 *
824
+	 * @return void
825
+	 * @throws EE_Error
826
+	 * @throws ReflectionException
827
+	 */
828
+	public function verify_cpt_object()
829
+	{
830
+		$label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
831
+		// verify event object
832
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
833
+			throw new EE_Error(
834
+				sprintf(
835
+					esc_html__(
836
+						'Something has gone wrong with the page load because we are unable to set up the object for the %1$s.  This usually happens when the given id for the page route is NOT for the correct custom post type for this page',
837
+						'event_espresso'
838
+					),
839
+					$label
840
+				)
841
+			);
842
+		}
843
+		// if auto-draft then throw an error
844
+		if ($this->_cpt_model_obj->get('status') === 'auto-draft') {
845
+			EE_Error::overwrite_errors();
846
+			EE_Error::add_error(
847
+				sprintf(
848
+					esc_html__(
849
+						'This %1$s was saved without a title, description, or excerpt which means that none of the extra details you added were saved properly.  All autodrafts will show up in the "draft" view of your event list table.  You can delete them from there. Please click the "Add %1$s" button to refresh and restart.',
850
+						'event_espresso'
851
+					),
852
+					$label
853
+				),
854
+				__FILE__,
855
+				__FUNCTION__,
856
+				__LINE__
857
+			);
858
+		}
859
+	}
860
+
861
+
862
+	/**
863
+	 * admin_footer_scripts_global
864
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
865
+	 * will apply on ALL EE_Admin pages.
866
+	 *
867
+	 * @return void
868
+	 */
869
+	public function admin_footer_scripts_global()
870
+	{
871
+		$this->_add_admin_page_ajax_loading_img();
872
+		$this->_add_admin_page_overlay();
873
+	}
874
+
875
+
876
+	/**
877
+	 * add in any global scripts for cpt routes
878
+	 *
879
+	 * @return void
880
+	 */
881
+	public function load_global_scripts_styles()
882
+	{
883
+		parent::load_global_scripts_styles();
884
+		if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
885
+			// setup custom post status object for localize script but only if we've got a cpt object
886
+			$statuses = $this->_cpt_model_obj->get_custom_post_statuses();
887
+			if (! empty($statuses)) {
888
+				// get ALL statuses!
889
+				$statuses = $this->_cpt_model_obj->get_all_post_statuses();
890
+				// setup object
891
+				$ee_cpt_statuses = [];
892
+				foreach ($statuses as $status => $label) {
893
+					$ee_cpt_statuses[ $status ] = [
894
+						'label'      => $label,
895
+						'save_label' => sprintf(
896
+							wp_strip_all_tags(__('Save as %s', 'event_espresso')),
897
+							$label
898
+						),
899
+					];
900
+				}
901
+				wp_localize_script('ee_admin_js', 'eeCPTstatuses', $ee_cpt_statuses);
902
+			}
903
+		}
904
+	}
905
+
906
+
907
+	/**
908
+	 * This is a wrapper for the insert/update routes for cpt items so we can add things that are common to ALL
909
+	 * insert/updates
910
+	 *
911
+	 * @param int     $post_id ID of post being updated
912
+	 * @param WP_Post $post    Post object from WP
913
+	 * @param bool    $update  Whether this is an update or a new save.
914
+	 * @return void
915
+	 * @throws EE_Error
916
+	 * @throws ReflectionException
917
+	 */
918
+	public function insert_update(int $post_id, WP_Post $post, bool $update)
919
+	{
920
+		// make sure that if this is a revision OR trash action that we don't do any updates!
921
+		$action = $this->request->getRequestParam('action');
922
+		if ($action === 'restore' || $action === 'trash') {
923
+			return;
924
+		}
925
+		$this->_set_model_object($post_id, true, 'insert_update');
926
+		// if our cpt object is not instantiated and its NOT the same post_id as what is triggering this callback, then exit.
927
+		if (
928
+			$update
929
+			&& (
930
+				! $this->_cpt_model_obj instanceof EE_CPT_Base
931
+				|| $this->_cpt_model_obj->ID() !== $post_id
932
+			)
933
+		) {
934
+			return;
935
+		}
936
+		// check for autosave and update our req_data property accordingly.
937
+		/*if ( defined('DOING_AUTOSAVE') && DOING_AUTOSAVE && isset( $this->_req_data['ee_autosave_data'] ) ) {
938 938
             foreach( (array) $this->_req_data['ee_autosave_data'] as $id => $values ) {
939 939
 
940 940
                 foreach ( (array) $values as $key => $value ) {
@@ -944,548 +944,548 @@  discard block
 block discarded – undo
944 944
 
945 945
         }/**/ // TODO reactivate after autosave is implemented in 4.2
946 946
 
947
-        // take care of updating any selected page_template IF this cpt supports it.
948
-
949
-        $page_template = $this->request->getRequestParam('page_template');
950
-        if ($this->_supports_page_templates($post->post_type) && ! empty($page_template)) {
951
-            // wp version aware.
952
-            if (RecommendedVersions::compareWordPressVersion('4.7')) {
953
-                $page_templates = wp_get_theme()->get_page_templates();
954
-            } else {
955
-                $post->page_template = $page_template;
956
-                $page_templates      = wp_get_theme()->get_page_templates($post);
957
-            }
958
-            if ($page_template !== 'default' && ! isset($page_templates[ $page_template ])) {
959
-                EE_Error::add_error(
960
-                    esc_html__('Invalid Page Template.', 'event_espresso'),
961
-                    __FILE__,
962
-                    __FUNCTION__,
963
-                    __LINE__
964
-                );
965
-            } else {
966
-                update_post_meta($post_id, '_wp_page_template', $page_template);
967
-            }
968
-        }
969
-        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
970
-            return;
971
-        } //TODO we'll remove this after reimplementing autosave in 4.2
972
-        $this->_insert_update_cpt_item($post_id, $post);
973
-    }
974
-
975
-
976
-    /**
977
-     * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
978
-     * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
979
-     * so we don't have to check for our CPT.
980
-     *
981
-     * @param int $post_id ID of the post
982
-     * @return void
983
-     */
984
-    public function dont_permanently_delete_ee_cpts(int $post_id)
985
-    {
986
-        // only do this if we're actually processing one of our CPTs
987
-        // if our cpt object isn't existent then get out immediately.
988
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
989
-            return;
990
-        }
991
-        delete_post_meta($post_id, '_wp_trash_meta_status');
992
-        delete_post_meta($post_id, '_wp_trash_meta_time');
993
-        // our cpts may have comments so let's take care of that too
994
-        delete_post_meta($post_id, '_wp_trash_meta_comments_status');
995
-    }
996
-
997
-
998
-    /**
999
-     * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1000
-     * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1001
-     * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1002
-     *
1003
-     * @param int $post_id     ID of cpt item
1004
-     * @param int $revision_id ID of revision being restored
1005
-     * @return void
1006
-     */
1007
-    public function restore_revision(int $post_id, int $revision_id)
1008
-    {
1009
-        $this->_restore_cpt_item($post_id, $revision_id);
1010
-        // global action
1011
-        do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1012
-        // class specific action so you can limit hooking into a specific page.
1013
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1014
-    }
1015
-
1016
-
1017
-    /**
1018
-     * @param int $post_id     ID of cpt item
1019
-     * @param int $revision_id ID of revision for item
1020
-     * @return void
1021
-     * @see restore_revision() for details
1022
-     */
1023
-    abstract protected function _restore_cpt_item(int $post_id, int $revision_id);
1024
-
1025
-
1026
-    /**
1027
-     * Execution of this method is added to the end of the load_page_dependencies method in the parent
1028
-     * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1029
-     * To fix we have to reset the current_screen using the page_slug
1030
-     * (which is identical - or should be - to our registered_post_type id.)
1031
-     * Also, since the core WP file loads the admin_header.php for WP
1032
-     * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1033
-     * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1034
-     *
1035
-     * @return void
1036
-     * @throws EE_Error
1037
-     * @throws ReflectionException
1038
-     */
1039
-    public function modify_current_screen()
1040
-    {
1041
-        // ONLY do this if the current page_route IS a cpt route
1042
-        if (! $this->_cpt_route) {
1043
-            return;
1044
-        }
1045
-        // routing things REALLY early b/c this is a cpt admin page
1046
-        set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1047
-        $this->_current_screen       = get_current_screen();
1048
-        $this->_current_screen->base = 'event-espresso';
1049
-        $this->_add_help_tabs(); // we make sure we add any help tabs back in!
1050
-        /*try {
947
+		// take care of updating any selected page_template IF this cpt supports it.
948
+
949
+		$page_template = $this->request->getRequestParam('page_template');
950
+		if ($this->_supports_page_templates($post->post_type) && ! empty($page_template)) {
951
+			// wp version aware.
952
+			if (RecommendedVersions::compareWordPressVersion('4.7')) {
953
+				$page_templates = wp_get_theme()->get_page_templates();
954
+			} else {
955
+				$post->page_template = $page_template;
956
+				$page_templates      = wp_get_theme()->get_page_templates($post);
957
+			}
958
+			if ($page_template !== 'default' && ! isset($page_templates[ $page_template ])) {
959
+				EE_Error::add_error(
960
+					esc_html__('Invalid Page Template.', 'event_espresso'),
961
+					__FILE__,
962
+					__FUNCTION__,
963
+					__LINE__
964
+				);
965
+			} else {
966
+				update_post_meta($post_id, '_wp_page_template', $page_template);
967
+			}
968
+		}
969
+		if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
970
+			return;
971
+		} //TODO we'll remove this after reimplementing autosave in 4.2
972
+		$this->_insert_update_cpt_item($post_id, $post);
973
+	}
974
+
975
+
976
+	/**
977
+	 * This hooks into the wp_trash_post() function and removes the `_wp_trash_meta_status` and `_wp_trash_meta_time`
978
+	 * post meta IF the trashed post is one of our CPT's - note this method should only be called with our cpt routes
979
+	 * so we don't have to check for our CPT.
980
+	 *
981
+	 * @param int $post_id ID of the post
982
+	 * @return void
983
+	 */
984
+	public function dont_permanently_delete_ee_cpts(int $post_id)
985
+	{
986
+		// only do this if we're actually processing one of our CPTs
987
+		// if our cpt object isn't existent then get out immediately.
988
+		if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
989
+			return;
990
+		}
991
+		delete_post_meta($post_id, '_wp_trash_meta_status');
992
+		delete_post_meta($post_id, '_wp_trash_meta_time');
993
+		// our cpts may have comments so let's take care of that too
994
+		delete_post_meta($post_id, '_wp_trash_meta_comments_status');
995
+	}
996
+
997
+
998
+	/**
999
+	 * This is a wrapper for the restore_cpt_revision route for cpt items so we can make sure that when a revision is
1000
+	 * triggered that we restore related items.  In order to work cpt classes MUST have a restore_cpt_revision method
1001
+	 * in them. We also have our OWN action in here so addons can hook into the restore process easily.
1002
+	 *
1003
+	 * @param int $post_id     ID of cpt item
1004
+	 * @param int $revision_id ID of revision being restored
1005
+	 * @return void
1006
+	 */
1007
+	public function restore_revision(int $post_id, int $revision_id)
1008
+	{
1009
+		$this->_restore_cpt_item($post_id, $revision_id);
1010
+		// global action
1011
+		do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1012
+		// class specific action so you can limit hooking into a specific page.
1013
+		do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1014
+	}
1015
+
1016
+
1017
+	/**
1018
+	 * @param int $post_id     ID of cpt item
1019
+	 * @param int $revision_id ID of revision for item
1020
+	 * @return void
1021
+	 * @see restore_revision() for details
1022
+	 */
1023
+	abstract protected function _restore_cpt_item(int $post_id, int $revision_id);
1024
+
1025
+
1026
+	/**
1027
+	 * Execution of this method is added to the end of the load_page_dependencies method in the parent
1028
+	 * so that we can fix a bug where default core metaboxes were not being called in the sidebar.
1029
+	 * To fix we have to reset the current_screen using the page_slug
1030
+	 * (which is identical - or should be - to our registered_post_type id.)
1031
+	 * Also, since the core WP file loads the admin_header.php for WP
1032
+	 * (and there are a bunch of other things edit-form-advanced.php loads that need to happen really early)
1033
+	 * we need to load it NOW, hence our _route_admin_request in here. (Otherwise screen options won't be set).
1034
+	 *
1035
+	 * @return void
1036
+	 * @throws EE_Error
1037
+	 * @throws ReflectionException
1038
+	 */
1039
+	public function modify_current_screen()
1040
+	{
1041
+		// ONLY do this if the current page_route IS a cpt route
1042
+		if (! $this->_cpt_route) {
1043
+			return;
1044
+		}
1045
+		// routing things REALLY early b/c this is a cpt admin page
1046
+		set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1047
+		$this->_current_screen       = get_current_screen();
1048
+		$this->_current_screen->base = 'event-espresso';
1049
+		$this->_add_help_tabs(); // we make sure we add any help tabs back in!
1050
+		/*try {
1051 1051
             $this->_route_admin_request();
1052 1052
         } catch ( EE_Error $e ) {
1053 1053
             $e->get_error();
1054 1054
         }/**/
1055
-    }
1056
-
1057
-
1058
-    /**
1059
-     * This allows child classes to modify the default editor title that appears when people add a new or edit an
1060
-     * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1061
-     * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1062
-     * default to be.
1063
-     *
1064
-     * @param string|null $title The new title (or existing if there is no editor_title defined)
1065
-     * @return string|null
1066
-     */
1067
-    public function add_custom_editor_default_title(?string $title): ?string
1068
-    {
1069
-        return $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ] ?? $title;
1070
-    }
1071
-
1072
-
1073
-    /**
1074
-     * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1075
-     *
1076
-     * @param string $shortlink   The already generated shortlink
1077
-     * @param int    $id          Post ID for this item
1078
-     * @return string
1079
-     * @deprecated 5.0.0.p
1080
-     * @see EventShortlinkButton::addButton()
1081
-     */
1082
-    public function add_shortlink_button_to_editor(string $shortlink, int $id): string
1083
-    {
1084
-        return EventShortlinkButton::addButton($shortlink, $id);
1085
-    }
1086
-
1087
-
1088
-    /**
1089
-     * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1090
-     * already run in modify_current_screen())
1091
-     *
1092
-     * @return void
1093
-     * @throws EE_Error
1094
-     * @throws ReflectionException
1095
-     * @throws Throwable
1096
-     */
1097
-    public function route_admin_request()
1098
-    {
1099
-        if ($this->_cpt_route) {
1100
-            return;
1101
-        }
1102
-        try {
1103
-            $this->_route_admin_request();
1104
-        } catch (EE_Error $e) {
1105
-            $e->get_error();
1106
-        }
1107
-    }
1108
-
1109
-
1110
-    /**
1111
-     * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1112
-     *
1113
-     * @return void
1114
-     */
1115
-    public function cpt_post_form_hidden_input()
1116
-    {
1117
-        // we're also going to add the route value and the current page so we can direct autosave parsing correctly
1118
-        echo '
1055
+	}
1056
+
1057
+
1058
+	/**
1059
+	 * This allows child classes to modify the default editor title that appears when people add a new or edit an
1060
+	 * existing CPT item.     * This uses the _labels property set by the child class via _define_page_props. Just make
1061
+	 * sure you have a key in _labels property that equals 'editor_title' and the value can be whatever you want the
1062
+	 * default to be.
1063
+	 *
1064
+	 * @param string|null $title The new title (or existing if there is no editor_title defined)
1065
+	 * @return string|null
1066
+	 */
1067
+	public function add_custom_editor_default_title(?string $title): ?string
1068
+	{
1069
+		return $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ] ?? $title;
1070
+	}
1071
+
1072
+
1073
+	/**
1074
+	 * hooks into the wp_get_shortlink button and makes sure that the shortlink gets generated
1075
+	 *
1076
+	 * @param string $shortlink   The already generated shortlink
1077
+	 * @param int    $id          Post ID for this item
1078
+	 * @return string
1079
+	 * @deprecated 5.0.0.p
1080
+	 * @see EventShortlinkButton::addButton()
1081
+	 */
1082
+	public function add_shortlink_button_to_editor(string $shortlink, int $id): string
1083
+	{
1084
+		return EventShortlinkButton::addButton($shortlink, $id);
1085
+	}
1086
+
1087
+
1088
+	/**
1089
+	 * overriding the parent route_admin_request method so we DON'T run the route twice on cpt core page loads (it's
1090
+	 * already run in modify_current_screen())
1091
+	 *
1092
+	 * @return void
1093
+	 * @throws EE_Error
1094
+	 * @throws ReflectionException
1095
+	 * @throws Throwable
1096
+	 */
1097
+	public function route_admin_request()
1098
+	{
1099
+		if ($this->_cpt_route) {
1100
+			return;
1101
+		}
1102
+		try {
1103
+			$this->_route_admin_request();
1104
+		} catch (EE_Error $e) {
1105
+			$e->get_error();
1106
+		}
1107
+	}
1108
+
1109
+
1110
+	/**
1111
+	 * Add a hidden form input to cpt core pages so that we know to do redirects to our routes on saves
1112
+	 *
1113
+	 * @return void
1114
+	 */
1115
+	public function cpt_post_form_hidden_input()
1116
+	{
1117
+		// we're also going to add the route value and the current page so we can direct autosave parsing correctly
1118
+		echo '
1119 1119
         <input type="hidden" name="ee_cpt_item_redirect_url" value="' . esc_url_raw($this->_admin_base_url) . '"/>
1120 1120
         <div id="ee-cpt-hidden-inputs">
1121 1121
             <input type="hidden" id="current_route" name="current_route" value="' . esc_attr($this->_current_view) . '"/>
1122 1122
             <input type="hidden" id="current_page" name="current_page" value="' . esc_attr($this->page_slug) . '"/>
1123 1123
         </div>';
1124
-    }
1125
-
1126
-
1127
-    /**
1128
-     * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1129
-     *
1130
-     * @param string $location Original location url
1131
-     * @return string           new (or original) url to redirect to.
1132
-     * @throws EE_Error
1133
-     */
1134
-    public function revision_redirect(string $location): string
1135
-    {
1136
-        // get revision
1137
-        $revision = $this->request->getRequestParam('revision');
1138
-        // can't do anything without revision so let's get out if not present
1139
-        if (empty($revision)) {
1140
-            return $location;
1141
-        }
1142
-        // get rev_post_data
1143
-        $rev        = get_post($revision);
1144
-        $admin_url  = $this->_admin_base_url;
1145
-        $query_args = [
1146
-            'action'   => 'edit',
1147
-            'post'     => $rev->post_parent,
1148
-            'revision' => $revision,
1149
-            'message'  => 5,
1150
-        ];
1151
-        $this->_process_notices($query_args, true);
1152
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1153
-    }
1154
-
1155
-
1156
-    /**
1157
-     * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1158
-     *
1159
-     * @param string|null $link     the original generated link
1160
-     * @param int    $id            post id
1161
-     * @return string               the link
1162
-     */
1163
-    public function modify_edit_post_link(?string $link, int $id): ?string
1164
-    {
1165
-        $post = get_post($id);
1166
-        $action = $this->request->getRequestParam('action');
1167
-        if (
1168
-            empty($action)
1169
-            || ! isset($this->_cpt_routes[ $action ])
1170
-            || $post->post_type !== $this->_cpt_routes[ $action ]
1171
-        ) {
1172
-            return $link;
1173
-        }
1174
-        $query_args = [
1175
-            'action' => $this->_cpt_edit_routes[ $post->post_type ] ?? 'edit',
1176
-            'post'   => $id,
1177
-        ];
1178
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1179
-    }
1180
-
1181
-
1182
-    /**
1183
-     * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1184
-     * our routes.
1185
-     *
1186
-     * @param string|null $delete_link      original delete link
1187
-     * @param int    $post_id               id of cpt object
1188
-     * @return null|string                  new delete link
1189
-     * @throws EE_Error
1190
-     * @throws ReflectionException
1191
-     */
1192
-    public function modify_delete_post_link(?string $delete_link, int $post_id): ?string
1193
-    {
1194
-        $post = get_post($post_id);
1195
-        $action = $this->request->getRequestParam('action');
1196
-        if (
1197
-            ! $post instanceof WP_Post
1198
-            || empty($action)
1199
-            || ! isset($this->_cpt_routes[ $action ])
1200
-            || $post->post_type !== $this->_cpt_routes[ $action ]
1201
-        ) {
1202
-            return $delete_link;
1203
-        }
1204
-        $this->_set_model_object($post->ID, true);
1205
-
1206
-        // returns something like `trash_event` or `trash_attendee` or `trash_venue`
1207
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1208
-
1209
-        return EE_Admin_Page::add_query_args_and_nonce(
1210
-            [
1211
-                'page'   => $this->request->getRequestParam('page'),
1212
-                'action' => $action,
1213
-                $this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name() => $post->ID,
1214
-            ],
1215
-            admin_url()
1216
-        );
1217
-    }
1218
-
1219
-
1220
-    /**
1221
-     * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1222
-     * so that we can hijack the default redirect locations for wp custom post types
1223
-     * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1224
-     *
1225
-     * @param string $location This is the incoming currently set redirect location
1226
-     * @param string $post_id  This is the 'ID' value of the wp_posts table
1227
-     * @return string           the new location to redirect to
1228
-     * @throws EE_Error
1229
-     */
1230
-    public function cpt_post_location_redirect(string $location, string $post_id): string
1231
-    {
1232
-        // we DO have a match so let's setup the url
1233
-        // we have to get the post to determine our route
1234
-        $post       = get_post($post_id);
1235
-        $edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1236
-        // shared query_args
1237
-        $query_args = ['action' => $edit_route, 'post' => $post_id];
1238
-
1239
-        $save = $this->request->getRequestParam('save');
1240
-        $publish = $this->request->getRequestParam('publish');
1241
-        $add_meta = $this->request->getRequestParam('addmeta');
1242
-        $delete_meta = $this->request->getRequestParam('deletemeta');
1243
-        if ($save || $publish) {
1244
-            $status = get_post_status($post_id);
1245
-            if ($publish) {
1246
-                switch ($status) {
1247
-                    case 'pending':
1248
-                        $message = 8;
1249
-                        break;
1250
-                    case 'future':
1251
-                        $message = 9;
1252
-                        break;
1253
-                    default:
1254
-                        $message = 6;
1255
-                }
1256
-            } else {
1257
-                $message = 'draft' === $status ? 10 : 1;
1258
-            }
1259
-        } elseif ($add_meta) {
1260
-            $message = 2;
1261
-        } elseif ($delete_meta) {
1262
-            $message = 3;
1263
-        } elseif ($this->request->getRequestParam('action') === 'post-quickpress-save-cont') {
1264
-            $message = 7;
1265
-        } else {
1266
-            $message = 4;
1267
-        }
1268
-        // change the message if the post type is not viewable on the frontend
1269
-        $this->_cpt_object = get_post_type_object($post->post_type);
1270
-
1271
-        $query_args['message'] = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1272
-        $this->_process_notices($query_args, true);
1273
-        return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1274
-    }
1275
-
1276
-
1277
-    /**
1278
-     * This method is called to inject nav tabs on core WP cpt pages
1279
-     *
1280
-     * @return void
1281
-     * @throws EE_Error
1282
-     */
1283
-    public function inject_nav_tabs()
1284
-    {
1285
-        echo wp_kses($this->_get_main_nav_tabs(), AllowedTags::getWithFormTags());
1286
-    }
1287
-
1288
-
1289
-    /**
1290
-     * This just sets up the post update messages when an update form is loaded
1291
-     *
1292
-     * @param array $messages the original messages array
1293
-     * @return array           the new messages array
1294
-     */
1295
-    public function post_update_messages(array $messages): array
1296
-    {
1297
-        global $post;
1298
-        $id       = $this->request->getRequestParam('post');
1299
-        $id       = empty($id) && is_object($post) ? $post->ID : null;
1300
-        $revision = $this->request->getRequestParam('revision', 0, 'int');
1301
-
1302
-        $messages[ $post->post_type ] = [
1303
-            0  => '', // Unused. Messages start at index 1.
1304
-            1  => sprintf(
1305
-                esc_html__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1306
-                $this->_cpt_object->labels->singular_name,
1307
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1308
-                '</a>'
1309
-            ),
1310
-            2  => esc_html__('Custom field updated', 'event_espresso'),
1311
-            3  => esc_html__('Custom field deleted.', 'event_espresso'),
1312
-            4  => sprintf(esc_html__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1313
-            5  => $revision
1314
-                ? sprintf(
1315
-                    esc_html__('%s restored to revision from %s', 'event_espresso'),
1316
-                    $this->_cpt_object->labels->singular_name,
1317
-                    wp_post_revision_title($revision, false)
1318
-                )
1319
-                : false,
1320
-            6  => sprintf(
1321
-                esc_html__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1322
-                $this->_cpt_object->labels->singular_name,
1323
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1324
-                '</a>'
1325
-            ),
1326
-            7  => sprintf(esc_html__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1327
-            8  => sprintf(
1328
-                esc_html__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1329
-                $this->_cpt_object->labels->singular_name,
1330
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1331
-                '</a>'
1332
-            ),
1333
-            9  => sprintf(
1334
-                esc_html__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1335
-                $this->_cpt_object->labels->singular_name,
1336
-                '<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1337
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1338
-                '</a>'
1339
-            ),
1340
-            10 => sprintf(
1341
-                esc_html__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1342
-                $this->_cpt_object->labels->singular_name,
1343
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1344
-                '</a>'
1345
-            ),
1346
-        ];
1347
-        return $messages;
1348
-    }
1349
-
1350
-
1351
-    /**
1352
-     * default method for the 'create_new' route for cpt admin pages.
1353
-     * For reference what to include in here, see wp-admin/post-new.php
1354
-     *
1355
-     * @return void
1356
-     */
1357
-    protected function _create_new_cpt_item()
1358
-    {
1359
-        // gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1360
-        global $post, $title, $post_type, $post_type_object;
1361
-        $post_type        = $this->_cpt_routes[ $this->_req_action ];
1362
-        $post_type_object = $this->_cpt_object;
1363
-        $title            = $post_type_object->labels->add_new_item;
1364
-        $post             = $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1365
-        add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1366
-        // modify the default editor title field with default title.
1367
-        add_filter('enter_title_here', [$this, 'add_custom_editor_default_title']);
1368
-        $this->loadEditorTemplate();
1369
-    }
1370
-
1371
-
1372
-    /**
1373
-     * Enqueues auto-save and loads the editor template
1374
-     *
1375
-     * @param bool $creating
1376
-     */
1377
-    private function loadEditorTemplate(bool $creating = true)
1378
-    {
1379
-        if ($this->admin_config && ! $this->admin_config->useAdvancedEditor()) {
1380
-            add_filter('admin_body_class', function ($classes) {
1381
-                $classes .= ' espresso-legacy-editor';
1382
-                return $classes;
1383
-            });
1384
-        }
1385
-
1386
-        global $post, $title, $is_IE, $post_type, $post_type_object;
1387
-        // these vars are used by the template
1388
-        $editing = true;
1389
-        $post_ID = $post->ID;
1390
-        if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1391
-            // only enqueue autosave when creating event (necessary to get permalink/url generated)
1392
-            // otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1393
-            $action = $this->request->getRequestParam('action');
1394
-            if ($creating) {
1395
-                wp_enqueue_script('autosave');
1396
-            } elseif (
1397
-                isset($this->_cpt_routes[ $action ])
1398
-                && ! isset($this->_labels['hide_add_button_on_cpt_route'][ $action ])
1399
-            ) {
1400
-                $create_new_action = apply_filters(
1401
-                    'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1402
-                    'create_new',
1403
-                    $this
1404
-                );
1405
-                $post_new_file     = EE_Admin_Page::add_query_args_and_nonce(
1406
-                    [
1407
-                        'action' => $create_new_action,
1408
-                        'page'   => $this->page_slug,
1409
-                    ],
1410
-                    'admin.php'
1411
-                );
1412
-            }
1413
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1414
-        }
1415
-    }
1416
-
1417
-
1418
-    public function add_new_admin_page_global()
1419
-    {
1420
-        $admin_page = $this->request->getRequestParam('post', 0, DataType::INT) !== 0
1421
-            ? 'post-php'
1422
-            : 'post-new-php';
1423
-        ?>
1124
+	}
1125
+
1126
+
1127
+	/**
1128
+	 * This allows us to redirect the location of revision restores when they happen so it goes to our CPT routes.
1129
+	 *
1130
+	 * @param string $location Original location url
1131
+	 * @return string           new (or original) url to redirect to.
1132
+	 * @throws EE_Error
1133
+	 */
1134
+	public function revision_redirect(string $location): string
1135
+	{
1136
+		// get revision
1137
+		$revision = $this->request->getRequestParam('revision');
1138
+		// can't do anything without revision so let's get out if not present
1139
+		if (empty($revision)) {
1140
+			return $location;
1141
+		}
1142
+		// get rev_post_data
1143
+		$rev        = get_post($revision);
1144
+		$admin_url  = $this->_admin_base_url;
1145
+		$query_args = [
1146
+			'action'   => 'edit',
1147
+			'post'     => $rev->post_parent,
1148
+			'revision' => $revision,
1149
+			'message'  => 5,
1150
+		];
1151
+		$this->_process_notices($query_args, true);
1152
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $admin_url);
1153
+	}
1154
+
1155
+
1156
+	/**
1157
+	 * Modify the edit post link generated by wp core function so that EE CPTs get setup differently.
1158
+	 *
1159
+	 * @param string|null $link     the original generated link
1160
+	 * @param int    $id            post id
1161
+	 * @return string               the link
1162
+	 */
1163
+	public function modify_edit_post_link(?string $link, int $id): ?string
1164
+	{
1165
+		$post = get_post($id);
1166
+		$action = $this->request->getRequestParam('action');
1167
+		if (
1168
+			empty($action)
1169
+			|| ! isset($this->_cpt_routes[ $action ])
1170
+			|| $post->post_type !== $this->_cpt_routes[ $action ]
1171
+		) {
1172
+			return $link;
1173
+		}
1174
+		$query_args = [
1175
+			'action' => $this->_cpt_edit_routes[ $post->post_type ] ?? 'edit',
1176
+			'post'   => $id,
1177
+		];
1178
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1179
+	}
1180
+
1181
+
1182
+	/**
1183
+	 * Modify the trash link on our cpt edit pages so it has the required query var for triggering redirect properly on
1184
+	 * our routes.
1185
+	 *
1186
+	 * @param string|null $delete_link      original delete link
1187
+	 * @param int    $post_id               id of cpt object
1188
+	 * @return null|string                  new delete link
1189
+	 * @throws EE_Error
1190
+	 * @throws ReflectionException
1191
+	 */
1192
+	public function modify_delete_post_link(?string $delete_link, int $post_id): ?string
1193
+	{
1194
+		$post = get_post($post_id);
1195
+		$action = $this->request->getRequestParam('action');
1196
+		if (
1197
+			! $post instanceof WP_Post
1198
+			|| empty($action)
1199
+			|| ! isset($this->_cpt_routes[ $action ])
1200
+			|| $post->post_type !== $this->_cpt_routes[ $action ]
1201
+		) {
1202
+			return $delete_link;
1203
+		}
1204
+		$this->_set_model_object($post->ID, true);
1205
+
1206
+		// returns something like `trash_event` or `trash_attendee` or `trash_venue`
1207
+		$action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1208
+
1209
+		return EE_Admin_Page::add_query_args_and_nonce(
1210
+			[
1211
+				'page'   => $this->request->getRequestParam('page'),
1212
+				'action' => $action,
1213
+				$this->_cpt_model_obj->get_model()->get_primary_key_field()->get_name() => $post->ID,
1214
+			],
1215
+			admin_url()
1216
+		);
1217
+	}
1218
+
1219
+
1220
+	/**
1221
+	 * This is the callback for the 'redirect_post_location' filter in wp-admin/post.php
1222
+	 * so that we can hijack the default redirect locations for wp custom post types
1223
+	 * that WE'RE using and send back to OUR routes.  This should only be hooked in on the right route.
1224
+	 *
1225
+	 * @param string $location This is the incoming currently set redirect location
1226
+	 * @param string $post_id  This is the 'ID' value of the wp_posts table
1227
+	 * @return string           the new location to redirect to
1228
+	 * @throws EE_Error
1229
+	 */
1230
+	public function cpt_post_location_redirect(string $location, string $post_id): string
1231
+	{
1232
+		// we DO have a match so let's setup the url
1233
+		// we have to get the post to determine our route
1234
+		$post       = get_post($post_id);
1235
+		$edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1236
+		// shared query_args
1237
+		$query_args = ['action' => $edit_route, 'post' => $post_id];
1238
+
1239
+		$save = $this->request->getRequestParam('save');
1240
+		$publish = $this->request->getRequestParam('publish');
1241
+		$add_meta = $this->request->getRequestParam('addmeta');
1242
+		$delete_meta = $this->request->getRequestParam('deletemeta');
1243
+		if ($save || $publish) {
1244
+			$status = get_post_status($post_id);
1245
+			if ($publish) {
1246
+				switch ($status) {
1247
+					case 'pending':
1248
+						$message = 8;
1249
+						break;
1250
+					case 'future':
1251
+						$message = 9;
1252
+						break;
1253
+					default:
1254
+						$message = 6;
1255
+				}
1256
+			} else {
1257
+				$message = 'draft' === $status ? 10 : 1;
1258
+			}
1259
+		} elseif ($add_meta) {
1260
+			$message = 2;
1261
+		} elseif ($delete_meta) {
1262
+			$message = 3;
1263
+		} elseif ($this->request->getRequestParam('action') === 'post-quickpress-save-cont') {
1264
+			$message = 7;
1265
+		} else {
1266
+			$message = 4;
1267
+		}
1268
+		// change the message if the post type is not viewable on the frontend
1269
+		$this->_cpt_object = get_post_type_object($post->post_type);
1270
+
1271
+		$query_args['message'] = $message === 1 && ! $this->_cpt_object->publicly_queryable ? 4 : $message;
1272
+		$this->_process_notices($query_args, true);
1273
+		return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
1274
+	}
1275
+
1276
+
1277
+	/**
1278
+	 * This method is called to inject nav tabs on core WP cpt pages
1279
+	 *
1280
+	 * @return void
1281
+	 * @throws EE_Error
1282
+	 */
1283
+	public function inject_nav_tabs()
1284
+	{
1285
+		echo wp_kses($this->_get_main_nav_tabs(), AllowedTags::getWithFormTags());
1286
+	}
1287
+
1288
+
1289
+	/**
1290
+	 * This just sets up the post update messages when an update form is loaded
1291
+	 *
1292
+	 * @param array $messages the original messages array
1293
+	 * @return array           the new messages array
1294
+	 */
1295
+	public function post_update_messages(array $messages): array
1296
+	{
1297
+		global $post;
1298
+		$id       = $this->request->getRequestParam('post');
1299
+		$id       = empty($id) && is_object($post) ? $post->ID : null;
1300
+		$revision = $this->request->getRequestParam('revision', 0, 'int');
1301
+
1302
+		$messages[ $post->post_type ] = [
1303
+			0  => '', // Unused. Messages start at index 1.
1304
+			1  => sprintf(
1305
+				esc_html__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1306
+				$this->_cpt_object->labels->singular_name,
1307
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1308
+				'</a>'
1309
+			),
1310
+			2  => esc_html__('Custom field updated', 'event_espresso'),
1311
+			3  => esc_html__('Custom field deleted.', 'event_espresso'),
1312
+			4  => sprintf(esc_html__('%1$s updated.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1313
+			5  => $revision
1314
+				? sprintf(
1315
+					esc_html__('%s restored to revision from %s', 'event_espresso'),
1316
+					$this->_cpt_object->labels->singular_name,
1317
+					wp_post_revision_title($revision, false)
1318
+				)
1319
+				: false,
1320
+			6  => sprintf(
1321
+				esc_html__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1322
+				$this->_cpt_object->labels->singular_name,
1323
+				'<a href="' . esc_url(get_permalink($id)) . '">',
1324
+				'</a>'
1325
+			),
1326
+			7  => sprintf(esc_html__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1327
+			8  => sprintf(
1328
+				esc_html__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1329
+				$this->_cpt_object->labels->singular_name,
1330
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1331
+				'</a>'
1332
+			),
1333
+			9  => sprintf(
1334
+				esc_html__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1335
+				$this->_cpt_object->labels->singular_name,
1336
+				'<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1337
+				'<a target="_blank" href="' . esc_url(get_permalink($id)),
1338
+				'</a>'
1339
+			),
1340
+			10 => sprintf(
1341
+				esc_html__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1342
+				$this->_cpt_object->labels->singular_name,
1343
+				'<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1344
+				'</a>'
1345
+			),
1346
+		];
1347
+		return $messages;
1348
+	}
1349
+
1350
+
1351
+	/**
1352
+	 * default method for the 'create_new' route for cpt admin pages.
1353
+	 * For reference what to include in here, see wp-admin/post-new.php
1354
+	 *
1355
+	 * @return void
1356
+	 */
1357
+	protected function _create_new_cpt_item()
1358
+	{
1359
+		// gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1360
+		global $post, $title, $post_type, $post_type_object;
1361
+		$post_type        = $this->_cpt_routes[ $this->_req_action ];
1362
+		$post_type_object = $this->_cpt_object;
1363
+		$title            = $post_type_object->labels->add_new_item;
1364
+		$post             = $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1365
+		add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1366
+		// modify the default editor title field with default title.
1367
+		add_filter('enter_title_here', [$this, 'add_custom_editor_default_title']);
1368
+		$this->loadEditorTemplate();
1369
+	}
1370
+
1371
+
1372
+	/**
1373
+	 * Enqueues auto-save and loads the editor template
1374
+	 *
1375
+	 * @param bool $creating
1376
+	 */
1377
+	private function loadEditorTemplate(bool $creating = true)
1378
+	{
1379
+		if ($this->admin_config && ! $this->admin_config->useAdvancedEditor()) {
1380
+			add_filter('admin_body_class', function ($classes) {
1381
+				$classes .= ' espresso-legacy-editor';
1382
+				return $classes;
1383
+			});
1384
+		}
1385
+
1386
+		global $post, $title, $is_IE, $post_type, $post_type_object;
1387
+		// these vars are used by the template
1388
+		$editing = true;
1389
+		$post_ID = $post->ID;
1390
+		if (apply_filters('FHEE__EE_Admin_Page_CPT___create_new_cpt_item__replace_editor', false, $post) === false) {
1391
+			// only enqueue autosave when creating event (necessary to get permalink/url generated)
1392
+			// otherwise EE doesn't support autosave fully, so to prevent user confusion we disable it in edit context.
1393
+			$action = $this->request->getRequestParam('action');
1394
+			if ($creating) {
1395
+				wp_enqueue_script('autosave');
1396
+			} elseif (
1397
+				isset($this->_cpt_routes[ $action ])
1398
+				&& ! isset($this->_labels['hide_add_button_on_cpt_route'][ $action ])
1399
+			) {
1400
+				$create_new_action = apply_filters(
1401
+					'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1402
+					'create_new',
1403
+					$this
1404
+				);
1405
+				$post_new_file     = EE_Admin_Page::add_query_args_and_nonce(
1406
+					[
1407
+						'action' => $create_new_action,
1408
+						'page'   => $this->page_slug,
1409
+					],
1410
+					'admin.php'
1411
+				);
1412
+			}
1413
+			include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1414
+		}
1415
+	}
1416
+
1417
+
1418
+	public function add_new_admin_page_global()
1419
+	{
1420
+		$admin_page = $this->request->getRequestParam('post', 0, DataType::INT) !== 0
1421
+			? 'post-php'
1422
+			: 'post-new-php';
1423
+		?>
1424 1424
         <script type="text/javascript">
1425 1425
             adminpage = '<?php echo esc_js($admin_page); ?>';
1426 1426
         </script>
1427 1427
         <?php
1428
-    }
1429
-
1430
-
1431
-    /**
1432
-     * default method for the 'edit' route for cpt admin pages
1433
-     * For reference on what to put in here, refer to wp-admin/post.php
1434
-     *
1435
-     * @return void
1436
-     */
1437
-    protected function _edit_cpt_item()
1438
-    {
1439
-        global $post, $post_type, $post_type_object, $title;
1440
-        $post_id = $this->request->getRequestParam('post', 0, DataType::INT);
1441
-        $post    = $post_id ? get_post($post_id, OBJECT, 'edit') : null;
1442
-        if (empty($post)) {
1443
-            wp_die(
1444
-                esc_html__(
1445
-                    "You attempted to edit an item that doesn't exist. Perhaps it was deleted?",
1446
-                    'event_espresso'
1447
-                )
1448
-            );
1449
-        }
1450
-
1451
-        $post_lock = $this->request->getRequestParam('get-post-lock');
1452
-        if ($post_lock) {
1453
-            wp_set_post_lock($post_id);
1454
-            EEH_URL::safeRedirectAndExit(get_edit_post_link($post_id, 'url'));
1455
-        }
1456
-
1457
-        // template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1458
-        $post_type        = $this->_cpt_routes[ $this->_req_action ];
1459
-        $post_type_object = $this->_cpt_object;
1460
-        $title = $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1461
-                 ?? $post_type_object->labels->edit_item;
1462
-
1463
-        if (! wp_check_post_lock($post->ID)) {
1464
-            wp_set_post_lock($post->ID);
1465
-        }
1466
-        add_action('admin_footer', '_admin_notice_post_locked');
1467
-        if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1468
-            wp_enqueue_script('admin-comments');
1469
-            enqueue_comment_hotkeys_js();
1470
-        }
1471
-        add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1472
-        // modify the default editor title field with default title.
1473
-        add_filter('enter_title_here', [$this, 'add_custom_editor_default_title']);
1474
-        $this->loadEditorTemplate(false);
1475
-    }
1476
-
1477
-
1478
-
1479
-    /**
1480
-     * some getters
1481
-     */
1482
-    /**
1483
-     * This returns the protected _cpt_model_obj property
1484
-     *
1485
-     * @return EE_CPT_Base|null
1486
-     */
1487
-    public function get_cpt_model_obj(): ?EE_CPT_Base
1488
-    {
1489
-        return $this->_cpt_model_obj;
1490
-    }
1428
+	}
1429
+
1430
+
1431
+	/**
1432
+	 * default method for the 'edit' route for cpt admin pages
1433
+	 * For reference on what to put in here, refer to wp-admin/post.php
1434
+	 *
1435
+	 * @return void
1436
+	 */
1437
+	protected function _edit_cpt_item()
1438
+	{
1439
+		global $post, $post_type, $post_type_object, $title;
1440
+		$post_id = $this->request->getRequestParam('post', 0, DataType::INT);
1441
+		$post    = $post_id ? get_post($post_id, OBJECT, 'edit') : null;
1442
+		if (empty($post)) {
1443
+			wp_die(
1444
+				esc_html__(
1445
+					"You attempted to edit an item that doesn't exist. Perhaps it was deleted?",
1446
+					'event_espresso'
1447
+				)
1448
+			);
1449
+		}
1450
+
1451
+		$post_lock = $this->request->getRequestParam('get-post-lock');
1452
+		if ($post_lock) {
1453
+			wp_set_post_lock($post_id);
1454
+			EEH_URL::safeRedirectAndExit(get_edit_post_link($post_id, 'url'));
1455
+		}
1456
+
1457
+		// template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1458
+		$post_type        = $this->_cpt_routes[ $this->_req_action ];
1459
+		$post_type_object = $this->_cpt_object;
1460
+		$title = $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1461
+				 ?? $post_type_object->labels->edit_item;
1462
+
1463
+		if (! wp_check_post_lock($post->ID)) {
1464
+			wp_set_post_lock($post->ID);
1465
+		}
1466
+		add_action('admin_footer', '_admin_notice_post_locked');
1467
+		if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1468
+			wp_enqueue_script('admin-comments');
1469
+			enqueue_comment_hotkeys_js();
1470
+		}
1471
+		add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1472
+		// modify the default editor title field with default title.
1473
+		add_filter('enter_title_here', [$this, 'add_custom_editor_default_title']);
1474
+		$this->loadEditorTemplate(false);
1475
+	}
1476
+
1477
+
1478
+
1479
+	/**
1480
+	 * some getters
1481
+	 */
1482
+	/**
1483
+	 * This returns the protected _cpt_model_obj property
1484
+	 *
1485
+	 * @return EE_CPT_Base|null
1486
+	 */
1487
+	public function get_cpt_model_obj(): ?EE_CPT_Base
1488
+	{
1489
+		return $this->_cpt_model_obj;
1490
+	}
1491 1491
 }
Please login to merge, or discard this patch.
Spacing   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -155,7 +155,7 @@  discard block
 block discarded – undo
155 155
      */
156 156
     protected function getLoader(): LoaderInterface
157 157
     {
158
-        if (! $this->loader instanceof LoaderInterface) {
158
+        if ( ! $this->loader instanceof LoaderInterface) {
159 159
             $this->loader = LoaderFactory::getLoader();
160 160
         }
161 161
         return $this->loader;
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
             ],
180 180
             $this->_cpt_routes
181 181
         );
182
-        $cpt_route_action     = $this->_cpt_routes[ $this->raw_req_action ] ?? null;
182
+        $cpt_route_action = $this->_cpt_routes[$this->raw_req_action] ?? null;
183 183
         // let's see if the current route has a value for cpt_object_slug. if it does, we use that instead of the page
184 184
         $page              = $this->raw_req_page ?: $this->page_slug;
185 185
         $page              = $cpt_route_action ?: $page;
@@ -211,10 +211,10 @@  discard block
 block discarded – undo
211 211
         // possibly reset pagenow.
212 212
         if (
213 213
             $this->page_slug === $this->raw_req_page
214
-            && isset($this->_pagenow_map[ $this->raw_req_action ])
214
+            && isset($this->_pagenow_map[$this->raw_req_action])
215 215
         ) {
216 216
             global $pagenow, $hook_suffix;
217
-            $pagenow     = $this->_pagenow_map[ $this->raw_req_action ];
217
+            $pagenow     = $this->_pagenow_map[$this->raw_req_action];
218 218
             $hook_suffix = $pagenow;
219 219
         }
220 220
     }
@@ -246,7 +246,7 @@  discard block
 block discarded – undo
246 246
         if (empty($wp_meta_boxes)) {
247 247
             return;
248 248
         }
249
-        $current_metaboxes = $wp_meta_boxes[ $this->page_slug ] ?? [];
249
+        $current_metaboxes = $wp_meta_boxes[$this->page_slug] ?? [];
250 250
         foreach ($current_metaboxes as $box_context) {
251 251
             foreach ($box_context as $box_details) {
252 252
                 foreach ($box_details as $box) {
@@ -280,7 +280,7 @@  discard block
 block discarded – undo
280 280
             $this
281 281
         );
282 282
         $containers = apply_filters(
283
-            'FHEE__EE_Admin_Page_CPT__' . get_class($this) . '___load_autosave_scripts_styles__containers',
283
+            'FHEE__EE_Admin_Page_CPT__'.get_class($this).'___load_autosave_scripts_styles__containers',
284 284
             $containers,
285 285
             $this
286 286
         );
@@ -318,7 +318,7 @@  discard block
 block discarded – undo
318 318
     protected function _load_page_dependencies()
319 319
     {
320 320
         // we only add stuff if this is a cpt_route!
321
-        if (! $this->_cpt_route) {
321
+        if ( ! $this->_cpt_route) {
322 322
             parent::_load_page_dependencies();
323 323
             return;
324 324
         }
@@ -339,8 +339,8 @@  discard block
 block discarded – undo
339 339
         add_action('post_updated_messages', [$this, 'post_update_messages']);
340 340
         // This basically allows us to change the title of the "publish" metabox area
341 341
         // on CPT pages by setting a 'publishbox' value in the $_labels property array in the child class.
342
-        $screen = $this->_cpt_routes[ $this->_req_action ];
343
-        if (! empty($this->_labels['publishbox'])) {
342
+        $screen = $this->_cpt_routes[$this->_req_action];
343
+        if ( ! empty($this->_labels['publishbox'])) {
344 344
             $this->addMetaBox(
345 345
                 'submitdiv',
346 346
                 $this->getPublishBoxTitle(),
@@ -391,8 +391,8 @@  discard block
 block discarded – undo
391 391
         // This is for any plugins that are doing things properly
392 392
         // and hooking into the load page hook for core wp cpt routes.
393 393
         global $pagenow;
394
-        add_action('load-' . $pagenow, [$this, 'modify_current_screen'], 20);
395
-        do_action('load-' . $pagenow);
394
+        add_action('load-'.$pagenow, [$this, 'modify_current_screen'], 20);
395
+        do_action('load-'.$pagenow);
396 396
         add_action('admin_enqueue_scripts', [$this, 'setup_autosave_hooks'], 30);
397 397
         // we route REALLY early.
398 398
         try {
@@ -419,8 +419,8 @@  discard block
 block discarded – undo
419 419
                 'admin.php?page=espresso_registrations&action=contact_list',
420 420
             ],
421 421
             1 => [
422
-                'edit.php?post_type=' . $this->_cpt_object->name,
423
-                'admin.php?page=' . $this->_cpt_object->name,
422
+                'edit.php?post_type='.$this->_cpt_object->name,
423
+                'admin.php?page='.$this->_cpt_object->name,
424 424
             ],
425 425
         ];
426 426
         foreach ($routes_to_match as $route_matches) {
@@ -448,14 +448,14 @@  discard block
 block discarded – undo
448 448
             'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
449 449
         );
450 450
         $cpt_args          = $custom_post_types->getDefinitions();
451
-        $cpt_args          = isset($cpt_args[ $cpt_name ]) ? $cpt_args[ $cpt_name ]['args'] : [];
451
+        $cpt_args          = isset($cpt_args[$cpt_name]) ? $cpt_args[$cpt_name]['args'] : [];
452 452
         $cpt_has_support   = ! empty($cpt_args['page_templates']);
453 453
 
454 454
         $post_templates = wp_get_theme()->get_post_templates();
455 455
         // if there are $post_templates for this cpt, then we return false for this method because
456 456
         // that means we aren't going to load our page template manager and leave that up to the native
457 457
         // cpt template manager.
458
-        return ! isset($post_templates[ $cpt_name ]) ? $cpt_has_support : false;
458
+        return ! isset($post_templates[$cpt_name]) ? $cpt_has_support : false;
459 459
     }
460 460
 
461 461
 
@@ -512,7 +512,7 @@  discard block
 block discarded – undo
512 512
     {
513 513
         $statuses         = $this->_cpt_model_obj->get_custom_post_statuses();
514 514
         $cur_status_label = array_key_exists($this->_cpt_model_obj->status(), $statuses)
515
-            ? $statuses[ $this->_cpt_model_obj->status() ]
515
+            ? $statuses[$this->_cpt_model_obj->status()]
516 516
             : '';
517 517
         $template_args    = [
518 518
             'cur_status'            => $this->_cpt_model_obj->status(),
@@ -527,7 +527,7 @@  discard block
 block discarded – undo
527 527
             $template_args['statuses']         = $statuses;
528 528
         }
529 529
 
530
-        $template = EE_ADMIN_TEMPLATE . 'status_dropdown.template.php';
530
+        $template = EE_ADMIN_TEMPLATE.'status_dropdown.template.php';
531 531
         EEH_Template::display_template($template, $template_args);
532 532
     }
533 533
 
@@ -567,7 +567,7 @@  discard block
 block discarded – undo
567 567
         $nonce = $this->request->getRequestParam('autosavenonce');
568 568
         $this->_verify_nonce($nonce, 'autosave');
569 569
         // make sure we define doing autosave (cause WP isn't triggering this we want to make sure we define it)
570
-        if (! defined('DOING_AUTOSAVE')) {
570
+        if ( ! defined('DOING_AUTOSAVE')) {
571 571
             define('DOING_AUTOSAVE', true);
572 572
         }
573 573
         // if we made it here then the nonce checked out.  Let's run our methods and actions
@@ -578,7 +578,7 @@  discard block
 block discarded – undo
578 578
             $this->_template_args['success'] = true;
579 579
         }
580 580
         do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__global_after', $this);
581
-        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_' . get_class($this), $this);
581
+        do_action('AHEE__EE_Admin_Page_CPT__do_extra_autosave_stuff__after_'.get_class($this), $this);
582 582
         // now let's return json
583 583
         $this->_return_json();
584 584
     }
@@ -600,7 +600,7 @@  discard block
 block discarded – undo
600 600
             return;
601 601
         }
602 602
         // set page routes and page config but ONLY if we're not viewing a custom setup cpt route as defined in _cpt_routes
603
-        if (! empty($this->_cpt_object)) {
603
+        if ( ! empty($this->_cpt_object)) {
604 604
             $this->_page_routes = array_merge(
605 605
                 [
606 606
                     'create_new' => [$this, '_create_new_cpt_item'],
@@ -631,7 +631,7 @@  discard block
 block discarded – undo
631 631
             );
632 632
         }
633 633
         // load the next section only if this is a matching cpt route as set in the cpt routes array.
634
-        if (! isset($this->_cpt_routes[ $this->_req_action ])) {
634
+        if ( ! isset($this->_cpt_routes[$this->_req_action])) {
635 635
             return;
636 636
         }
637 637
         $this->_cpt_route = true;
@@ -672,7 +672,7 @@  discard block
 block discarded – undo
672 672
             empty($this->_cpt_model_names)
673 673
             || (
674 674
                 ! $ignore_route_check
675
-                && ! isset($this->_cpt_routes[ $this->_req_action ])
675
+                && ! isset($this->_cpt_routes[$this->_req_action])
676 676
             )
677 677
             || (
678 678
                 $this->_cpt_model_obj instanceof EE_CPT_Base
@@ -690,11 +690,11 @@  discard block
 block discarded – undo
690 690
                 'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions'
691 691
             );
692 692
             $model_names       = $custom_post_types->getCustomPostTypeModelNames($post_type);
693
-            if (isset($model_names[ $post_type ])) {
694
-                $model = EE_Registry::instance()->load_model($model_names[ $post_type ]);
693
+            if (isset($model_names[$post_type])) {
694
+                $model = EE_Registry::instance()->load_model($model_names[$post_type]);
695 695
             }
696 696
         } else {
697
-            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[ $this->_req_action ]);
697
+            $model = EE_Registry::instance()->load_model($this->_cpt_model_names[$this->_req_action]);
698 698
         }
699 699
         if ($model instanceof EEM_Base) {
700 700
             $this->_cpt_model_obj = ! empty($id) ? $model->get_one_by_ID($id) : $model->create_default_object();
@@ -722,8 +722,8 @@  discard block
 block discarded – undo
722 722
         $post           = get_post($post_ID);
723 723
         $post_type      = $post instanceof WP_Post ? $post->post_type : false;
724 724
         $current_route  = $this->request->getRequestParam('current_route', 'shouldneverwork');
725
-        $route_to_check = $post_type && isset($this->_cpt_routes[ $current_route ])
726
-            ? $this->_cpt_routes[ $current_route ]
725
+        $route_to_check = $post_type && isset($this->_cpt_routes[$current_route])
726
+            ? $this->_cpt_routes[$current_route]
727 727
             : '';
728 728
         add_filter('get_delete_post_link', [$this, 'modify_delete_post_link'], 10, 2);
729 729
         add_filter('get_edit_post_link', [$this, 'modify_edit_post_link'], 10, 2);
@@ -732,10 +732,10 @@  discard block
 block discarded – undo
732 732
         }
733 733
         // now let's filter redirect if we're on a revision page and the revision is for an event CPT.
734 734
         $revision = $this->request->getRequestParam('revision');
735
-        if (! empty($revision)) {
735
+        if ( ! empty($revision)) {
736 736
             $action = $this->request->getRequestParam('action');
737 737
             // doing a restore?
738
-            if (! empty($action) && $action === 'restore') {
738
+            if ( ! empty($action) && $action === 'restore') {
739 739
                 // get post for revision
740 740
                 $rev_post   = get_post($revision);
741 741
                 $rev_parent = get_post($rev_post->post_parent);
@@ -772,7 +772,7 @@  discard block
 block discarded – undo
772 772
     {
773 773
         $this->_set_model_object($post_id, true, 'trash');
774 774
         // if our cpt object isn't existent then get out immediately.
775
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
775
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
776 776
             return;
777 777
         }
778 778
         $this->trash_cpt_item($post_id);
@@ -791,7 +791,7 @@  discard block
 block discarded – undo
791 791
     {
792 792
         $this->_set_model_object($post_id, true, 'restore');
793 793
         // if our cpt object isn't existent then get out immediately.
794
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
794
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
795 795
             return;
796 796
         }
797 797
         $this->restore_cpt_item($post_id);
@@ -810,7 +810,7 @@  discard block
 block discarded – undo
810 810
     {
811 811
         $this->_set_model_object($post_id, true, 'delete');
812 812
         // if our cpt object isn't existent then get out immediately.
813
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
813
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base || $this->_cpt_model_obj->ID() !== $post_id) {
814 814
             return;
815 815
         }
816 816
         $this->delete_cpt_item($post_id);
@@ -829,7 +829,7 @@  discard block
 block discarded – undo
829 829
     {
830 830
         $label = ! empty($this->_cpt_object) ? $this->_cpt_object->labels->singular_name : $this->page_label;
831 831
         // verify event object
832
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
832
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
833 833
             throw new EE_Error(
834 834
                 sprintf(
835 835
                     esc_html__(
@@ -884,13 +884,13 @@  discard block
 block discarded – undo
884 884
         if ($this->_cpt_model_obj instanceof EE_CPT_Base) {
885 885
             // setup custom post status object for localize script but only if we've got a cpt object
886 886
             $statuses = $this->_cpt_model_obj->get_custom_post_statuses();
887
-            if (! empty($statuses)) {
887
+            if ( ! empty($statuses)) {
888 888
                 // get ALL statuses!
889 889
                 $statuses = $this->_cpt_model_obj->get_all_post_statuses();
890 890
                 // setup object
891 891
                 $ee_cpt_statuses = [];
892 892
                 foreach ($statuses as $status => $label) {
893
-                    $ee_cpt_statuses[ $status ] = [
893
+                    $ee_cpt_statuses[$status] = [
894 894
                         'label'      => $label,
895 895
                         'save_label' => sprintf(
896 896
                             wp_strip_all_tags(__('Save as %s', 'event_espresso')),
@@ -955,7 +955,7 @@  discard block
 block discarded – undo
955 955
                 $post->page_template = $page_template;
956 956
                 $page_templates      = wp_get_theme()->get_page_templates($post);
957 957
             }
958
-            if ($page_template !== 'default' && ! isset($page_templates[ $page_template ])) {
958
+            if ($page_template !== 'default' && ! isset($page_templates[$page_template])) {
959 959
                 EE_Error::add_error(
960 960
                     esc_html__('Invalid Page Template.', 'event_espresso'),
961 961
                     __FILE__,
@@ -985,7 +985,7 @@  discard block
 block discarded – undo
985 985
     {
986 986
         // only do this if we're actually processing one of our CPTs
987 987
         // if our cpt object isn't existent then get out immediately.
988
-        if (! $this->_cpt_model_obj instanceof EE_CPT_Base) {
988
+        if ( ! $this->_cpt_model_obj instanceof EE_CPT_Base) {
989 989
             return;
990 990
         }
991 991
         delete_post_meta($post_id, '_wp_trash_meta_status');
@@ -1010,7 +1010,7 @@  discard block
 block discarded – undo
1010 1010
         // global action
1011 1011
         do_action('AHEE_EE_Admin_Page_CPT__restore_revision', $post_id, $revision_id);
1012 1012
         // class specific action so you can limit hooking into a specific page.
1013
-        do_action('AHEE_EE_Admin_Page_CPT_' . get_class($this) . '__restore_revision', $post_id, $revision_id);
1013
+        do_action('AHEE_EE_Admin_Page_CPT_'.get_class($this).'__restore_revision', $post_id, $revision_id);
1014 1014
     }
1015 1015
 
1016 1016
 
@@ -1039,11 +1039,11 @@  discard block
 block discarded – undo
1039 1039
     public function modify_current_screen()
1040 1040
     {
1041 1041
         // ONLY do this if the current page_route IS a cpt route
1042
-        if (! $this->_cpt_route) {
1042
+        if ( ! $this->_cpt_route) {
1043 1043
             return;
1044 1044
         }
1045 1045
         // routing things REALLY early b/c this is a cpt admin page
1046
-        set_current_screen($this->_cpt_routes[ $this->_req_action ]);
1046
+        set_current_screen($this->_cpt_routes[$this->_req_action]);
1047 1047
         $this->_current_screen       = get_current_screen();
1048 1048
         $this->_current_screen->base = 'event-espresso';
1049 1049
         $this->_add_help_tabs(); // we make sure we add any help tabs back in!
@@ -1066,7 +1066,7 @@  discard block
 block discarded – undo
1066 1066
      */
1067 1067
     public function add_custom_editor_default_title(?string $title): ?string
1068 1068
     {
1069
-        return $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ] ?? $title;
1069
+        return $this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]] ?? $title;
1070 1070
     }
1071 1071
 
1072 1072
 
@@ -1116,10 +1116,10 @@  discard block
 block discarded – undo
1116 1116
     {
1117 1117
         // we're also going to add the route value and the current page so we can direct autosave parsing correctly
1118 1118
         echo '
1119
-        <input type="hidden" name="ee_cpt_item_redirect_url" value="' . esc_url_raw($this->_admin_base_url) . '"/>
1119
+        <input type="hidden" name="ee_cpt_item_redirect_url" value="' . esc_url_raw($this->_admin_base_url).'"/>
1120 1120
         <div id="ee-cpt-hidden-inputs">
1121
-            <input type="hidden" id="current_route" name="current_route" value="' . esc_attr($this->_current_view) . '"/>
1122
-            <input type="hidden" id="current_page" name="current_page" value="' . esc_attr($this->page_slug) . '"/>
1121
+            <input type="hidden" id="current_route" name="current_route" value="' . esc_attr($this->_current_view).'"/>
1122
+            <input type="hidden" id="current_page" name="current_page" value="' . esc_attr($this->page_slug).'"/>
1123 1123
         </div>';
1124 1124
     }
1125 1125
 
@@ -1166,13 +1166,13 @@  discard block
 block discarded – undo
1166 1166
         $action = $this->request->getRequestParam('action');
1167 1167
         if (
1168 1168
             empty($action)
1169
-            || ! isset($this->_cpt_routes[ $action ])
1170
-            || $post->post_type !== $this->_cpt_routes[ $action ]
1169
+            || ! isset($this->_cpt_routes[$action])
1170
+            || $post->post_type !== $this->_cpt_routes[$action]
1171 1171
         ) {
1172 1172
             return $link;
1173 1173
         }
1174 1174
         $query_args = [
1175
-            'action' => $this->_cpt_edit_routes[ $post->post_type ] ?? 'edit',
1175
+            'action' => $this->_cpt_edit_routes[$post->post_type] ?? 'edit',
1176 1176
             'post'   => $id,
1177 1177
         ];
1178 1178
         return EE_Admin_Page_CPT::add_query_args_and_nonce($query_args, $this->_admin_base_url);
@@ -1196,15 +1196,15 @@  discard block
 block discarded – undo
1196 1196
         if (
1197 1197
             ! $post instanceof WP_Post
1198 1198
             || empty($action)
1199
-            || ! isset($this->_cpt_routes[ $action ])
1200
-            || $post->post_type !== $this->_cpt_routes[ $action ]
1199
+            || ! isset($this->_cpt_routes[$action])
1200
+            || $post->post_type !== $this->_cpt_routes[$action]
1201 1201
         ) {
1202 1202
             return $delete_link;
1203 1203
         }
1204 1204
         $this->_set_model_object($post->ID, true);
1205 1205
 
1206 1206
         // returns something like `trash_event` or `trash_attendee` or `trash_venue`
1207
-        $action = 'trash_' . str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1207
+        $action = 'trash_'.str_replace('ee_', '', strtolower(get_class($this->_cpt_model_obj)));
1208 1208
 
1209 1209
         return EE_Admin_Page::add_query_args_and_nonce(
1210 1210
             [
@@ -1232,7 +1232,7 @@  discard block
 block discarded – undo
1232 1232
         // we DO have a match so let's setup the url
1233 1233
         // we have to get the post to determine our route
1234 1234
         $post       = get_post($post_id);
1235
-        $edit_route = $this->_cpt_edit_routes[ $post->post_type ];
1235
+        $edit_route = $this->_cpt_edit_routes[$post->post_type];
1236 1236
         // shared query_args
1237 1237
         $query_args = ['action' => $edit_route, 'post' => $post_id];
1238 1238
 
@@ -1299,12 +1299,12 @@  discard block
 block discarded – undo
1299 1299
         $id       = empty($id) && is_object($post) ? $post->ID : null;
1300 1300
         $revision = $this->request->getRequestParam('revision', 0, 'int');
1301 1301
 
1302
-        $messages[ $post->post_type ] = [
1302
+        $messages[$post->post_type] = [
1303 1303
             0  => '', // Unused. Messages start at index 1.
1304 1304
             1  => sprintf(
1305 1305
                 esc_html__('%1$s updated. %2$sView %1$s%3$s', 'event_espresso'),
1306 1306
                 $this->_cpt_object->labels->singular_name,
1307
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1307
+                '<a href="'.esc_url(get_permalink($id)).'">',
1308 1308
                 '</a>'
1309 1309
             ),
1310 1310
             2  => esc_html__('Custom field updated', 'event_espresso'),
@@ -1320,27 +1320,27 @@  discard block
 block discarded – undo
1320 1320
             6  => sprintf(
1321 1321
                 esc_html__('%1$s published. %2$sView %1$s%3$s', 'event_espresso'),
1322 1322
                 $this->_cpt_object->labels->singular_name,
1323
-                '<a href="' . esc_url(get_permalink($id)) . '">',
1323
+                '<a href="'.esc_url(get_permalink($id)).'">',
1324 1324
                 '</a>'
1325 1325
             ),
1326 1326
             7  => sprintf(esc_html__('%1$s saved.', 'event_espresso'), $this->_cpt_object->labels->singular_name),
1327 1327
             8  => sprintf(
1328 1328
                 esc_html__('%1$s submitted. %2$sPreview %1$s%3$s', 'event_espresso'),
1329 1329
                 $this->_cpt_object->labels->singular_name,
1330
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))) . '">',
1330
+                '<a target="_blank" href="'.esc_url(add_query_arg('preview', 'true', get_permalink($id))).'">',
1331 1331
                 '</a>'
1332 1332
             ),
1333 1333
             9  => sprintf(
1334 1334
                 esc_html__('%1$s scheduled for: %2$s. %3$s">Preview %1$s%3$s', 'event_espresso'),
1335 1335
                 $this->_cpt_object->labels->singular_name,
1336
-                '<strong>' . date_i18n('M j, Y @ G:i', strtotime($post->post_date)) . '</strong>',
1337
-                '<a target="_blank" href="' . esc_url(get_permalink($id)),
1336
+                '<strong>'.date_i18n('M j, Y @ G:i', strtotime($post->post_date)).'</strong>',
1337
+                '<a target="_blank" href="'.esc_url(get_permalink($id)),
1338 1338
                 '</a>'
1339 1339
             ),
1340 1340
             10 => sprintf(
1341 1341
                 esc_html__('%1$s draft updated. %2$s">Preview page%3$s', 'event_espresso'),
1342 1342
                 $this->_cpt_object->labels->singular_name,
1343
-                '<a target="_blank" href="' . esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1343
+                '<a target="_blank" href="'.esc_url(add_query_arg('preview', 'true', get_permalink($id))),
1344 1344
                 '</a>'
1345 1345
             ),
1346 1346
         ];
@@ -1358,10 +1358,10 @@  discard block
 block discarded – undo
1358 1358
     {
1359 1359
         // gather template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1360 1360
         global $post, $title, $post_type, $post_type_object;
1361
-        $post_type        = $this->_cpt_routes[ $this->_req_action ];
1361
+        $post_type        = $this->_cpt_routes[$this->_req_action];
1362 1362
         $post_type_object = $this->_cpt_object;
1363 1363
         $title            = $post_type_object->labels->add_new_item;
1364
-        $post             = $post = get_default_post_to_edit($this->_cpt_routes[ $this->_req_action ], true);
1364
+        $post             = $post = get_default_post_to_edit($this->_cpt_routes[$this->_req_action], true);
1365 1365
         add_action('admin_print_styles', [$this, 'add_new_admin_page_global']);
1366 1366
         // modify the default editor title field with default title.
1367 1367
         add_filter('enter_title_here', [$this, 'add_custom_editor_default_title']);
@@ -1377,7 +1377,7 @@  discard block
 block discarded – undo
1377 1377
     private function loadEditorTemplate(bool $creating = true)
1378 1378
     {
1379 1379
         if ($this->admin_config && ! $this->admin_config->useAdvancedEditor()) {
1380
-            add_filter('admin_body_class', function ($classes) {
1380
+            add_filter('admin_body_class', function($classes) {
1381 1381
                 $classes .= ' espresso-legacy-editor';
1382 1382
                 return $classes;
1383 1383
             });
@@ -1394,15 +1394,15 @@  discard block
 block discarded – undo
1394 1394
             if ($creating) {
1395 1395
                 wp_enqueue_script('autosave');
1396 1396
             } elseif (
1397
-                isset($this->_cpt_routes[ $action ])
1398
-                && ! isset($this->_labels['hide_add_button_on_cpt_route'][ $action ])
1397
+                isset($this->_cpt_routes[$action])
1398
+                && ! isset($this->_labels['hide_add_button_on_cpt_route'][$action])
1399 1399
             ) {
1400 1400
                 $create_new_action = apply_filters(
1401 1401
                     'FHEE__EE_Admin_Page_CPT___edit_cpt_item__create_new_action',
1402 1402
                     'create_new',
1403 1403
                     $this
1404 1404
                 );
1405
-                $post_new_file     = EE_Admin_Page::add_query_args_and_nonce(
1405
+                $post_new_file = EE_Admin_Page::add_query_args_and_nonce(
1406 1406
                     [
1407 1407
                         'action' => $create_new_action,
1408 1408
                         'page'   => $this->page_slug,
@@ -1410,7 +1410,7 @@  discard block
 block discarded – undo
1410 1410
                     'admin.php'
1411 1411
                 );
1412 1412
             }
1413
-            include_once WP_ADMIN_PATH . 'edit-form-advanced.php';
1413
+            include_once WP_ADMIN_PATH.'edit-form-advanced.php';
1414 1414
         }
1415 1415
     }
1416 1416
 
@@ -1455,16 +1455,16 @@  discard block
 block discarded – undo
1455 1455
         }
1456 1456
 
1457 1457
         // template vars for WP_ADMIN_PATH . 'edit-form-advanced.php'
1458
-        $post_type        = $this->_cpt_routes[ $this->_req_action ];
1458
+        $post_type        = $this->_cpt_routes[$this->_req_action];
1459 1459
         $post_type_object = $this->_cpt_object;
1460
-        $title = $this->_labels['editor_title'][ $this->_cpt_routes[ $this->_req_action ] ]
1460
+        $title = $this->_labels['editor_title'][$this->_cpt_routes[$this->_req_action]]
1461 1461
                  ?? $post_type_object->labels->edit_item;
1462 1462
 
1463
-        if (! wp_check_post_lock($post->ID)) {
1463
+        if ( ! wp_check_post_lock($post->ID)) {
1464 1464
             wp_set_post_lock($post->ID);
1465 1465
         }
1466 1466
         add_action('admin_footer', '_admin_notice_post_locked');
1467
-        if (post_type_supports($this->_cpt_routes[ $this->_req_action ], 'comments')) {
1467
+        if (post_type_supports($this->_cpt_routes[$this->_req_action], 'comments')) {
1468 1468
             wp_enqueue_script('admin-comments');
1469 1469
             enqueue_comment_hotkeys_js();
1470 1470
         }
Please login to merge, or discard this patch.
core/helpers/EEH_MSG_Template.helper.php 1 patch
Indentation   +1257 added lines, -1257 removed lines patch added patch discarded remove patch
@@ -14,1264 +14,1264 @@
 block discarded – undo
14 14
  */
15 15
 class EEH_MSG_Template
16 16
 {
17
-    /**
18
-     * Holds a collection of EE_Message_Template_Pack objects.
19
-     * @type EE_Messages_Template_Pack_Collection
20
-     */
21
-    protected static $_template_pack_collection;
22
-
23
-
24
-    /**
25
-     * @throws EE_Error
26
-     */
27
-    private static function _set_autoloader()
28
-    {
29
-        EED_Messages::set_autoloaders();
30
-    }
31
-
32
-
33
-    /**
34
-     * generate_new_templates
35
-     * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
36
-     * automatically create the defaults for the event.  The user would then be redirected to edit the default context
37
-     * for the event.
38
-     *
39
-     * @access protected
40
-     * @param string $messenger     the messenger we are generating templates for
41
-     * @param array  $message_types array of message types that the templates are generated for.
42
-     * @param int    $GRP_ID        If a non global template is being generated then it is expected we'll have a GRP_ID
43
-     *                              to use as the base for the new generated template.
44
-     * @param bool   $global        true indicates generating templates on messenger activation. false requires GRP_ID
45
-     *                              for event specific template generation.
46
-     * @return array  @see EEH_MSG_Template::_create_new_templates for the return value of each element in the array
47
-     *                for templates that are generated.  If this is an empty array then it means no templates were
48
-     *                generated which usually means there was an error.  Anything in the array with an empty value for
49
-     *                `MTP_context` means that it was not a new generated template but just reactivated (which only
50
-     *                happens for global templates that already exist in the database.
51
-     * @throws EE_Error
52
-     * @throws ReflectionException
53
-     */
54
-    public static function generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
55
-    {
56
-        // make sure message_type is an array.
57
-        $message_types = (array) $message_types;
58
-        $templates = array();
59
-
60
-        if (empty($messenger)) {
61
-            throw new EE_Error(esc_html__('We need a messenger to generate templates!', 'event_espresso'));
62
-        }
63
-
64
-        // if we STILL have empty $message_types then we need to generate an error message b/c we NEED message types to do the template files.
65
-        if (empty($message_types)) {
66
-            throw new EE_Error(esc_html__('We need at least one message type to generate templates!', 'event_espresso'));
67
-        }
68
-
69
-        EEH_MSG_Template::_set_autoloader();
70
-        foreach ($message_types as $message_type) {
71
-            // if this is global template generation.
72
-            if ($global) {
73
-                // let's attempt to get the GRP_ID for this combo IF GRP_ID is empty.
74
-                if (empty($GRP_ID)) {
75
-                    $GRP_ID = EEM_Message_Template_Group::instance()->get_one(
76
-                        array(
77
-                            array(
78
-                                'MTP_messenger'    => $messenger,
79
-                                'MTP_message_type' => $message_type,
80
-                                'MTP_is_global'    => true,
81
-                            ),
82
-                        )
83
-                    );
84
-                    $GRP_ID = $GRP_ID instanceof EE_Message_Template_Group ? $GRP_ID->ID() : 0;
85
-                }
86
-                // First let's determine if we already HAVE global templates for this messenger and message_type combination.
87
-                //  If we do then NO generation!!
88
-                if (EEH_MSG_Template::already_generated($messenger, $message_type, $GRP_ID)) {
89
-                    $templates[] = array(
90
-                        'GRP_ID' => $GRP_ID,
91
-                        'MTP_context' => '',
92
-                    );
93
-                    // we already have generated templates for this so let's go to the next message type.
94
-                    continue;
95
-                }
96
-            }
97
-            $new_message_template_group = EEH_MSG_Template::create_new_templates(
98
-                $messenger,
99
-                $message_type,
100
-                $GRP_ID,
101
-                $global
102
-            );
103
-
104
-            if (! $new_message_template_group) {
105
-                continue;
106
-            }
107
-            $templates[] = $new_message_template_group;
108
-        }
109
-
110
-        return $templates;
111
-    }
112
-
113
-
114
-    /**
115
-     * The purpose of this method is to determine if there are already generated templates in the database for the
116
-     * given variables.
117
-     *
118
-     * @param string $messenger    messenger
119
-     * @param string $message_type message type
120
-     * @param int    $GRP_ID       GRP ID ( if a custom template) (if not provided then we're just doing global
121
-     *                             template check)
122
-     * @return bool                true = generated, false = hasn't been generated.
123
-     * @throws EE_Error
124
-     */
125
-    public static function already_generated($messenger, $message_type, $GRP_ID = 0)
126
-    {
127
-        EEH_MSG_Template::_set_autoloader();
128
-        // what method we use depends on whether we have an GRP_ID or not
129
-        $count = empty($GRP_ID)
130
-            ? EEM_Message_Template::instance()->count(
131
-                array(
132
-                    array(
133
-                        'Message_Template_Group.MTP_messenger'    => $messenger,
134
-                        'Message_Template_Group.MTP_message_type' => $message_type,
135
-                        'Message_Template_Group.MTP_is_global'    => true
136
-                    )
137
-                )
138
-            )
139
-            : EEM_Message_Template::instance()->count(array( array( 'GRP_ID' => $GRP_ID ) ));
140
-
141
-        return $count > 0;
142
-    }
143
-
144
-
145
-    /**
146
-     * Updates all message templates matching the incoming messengers and message types to active status.
147
-     *
148
-     * @static
149
-     * @param array $messenger_names    Messenger slug
150
-     * @param array $message_type_names Message type slug
151
-     * @return  int                         count of updated records.
152
-     * @throws EE_Error
153
-     */
154
-    public static function update_to_active($messenger_names, $message_type_names)
155
-    {
156
-        $messenger_names = is_array($messenger_names) ? $messenger_names : array( $messenger_names );
157
-        $message_type_names = is_array($message_type_names) ? $message_type_names : array( $message_type_names );
158
-        return EEM_Message_Template_Group::instance()->update(
159
-            array( 'MTP_is_active' => 1 ),
160
-            array(
161
-                array(
162
-                    'MTP_messenger'     => array( 'IN', $messenger_names ),
163
-                    'MTP_message_type'  => array( 'IN', $message_type_names )
164
-                )
165
-            )
166
-        );
167
-    }
168
-
169
-
170
-    /**
171
-     * Updates all message template groups matching the incoming arguments to inactive status.
172
-     *
173
-     * @static
174
-     * @param array $messenger_names    The messenger slugs.
175
-     *                                  If empty then all templates matching the message types are marked inactive.
176
-     *                                  Otherwise only templates matching the messengers and message types.
177
-     * @param array $message_type_names The message type slugs.
178
-     *                                  If empty then all templates matching the messengers are marked inactive.
179
-     *                                  Otherwise only templates matching the messengers and message types.
180
-     *
181
-     * @return int  count of updated records.
182
-     * @throws EE_Error
183
-     */
184
-    public static function update_to_inactive($messenger_names = array(), $message_type_names = array())
185
-    {
186
-        return EEM_Message_Template_Group::instance()->deactivate_message_template_groups_for(
187
-            $messenger_names,
188
-            $message_type_names
189
-        );
190
-    }
191
-
192
-
193
-    /**
194
-     * The purpose of this function is to return all installed message objects
195
-     * (messengers and message type regardless of whether they are ACTIVE or not)
196
-     *
197
-     * @param string $type
198
-     * @return array array consisting of installed messenger objects and installed message type objects.
199
-     * @throws EE_Error
200
-     * @throws ReflectionException
201
-     * @deprecated 4.9.0
202
-     * @static
203
-     */
204
-    public static function get_installed_message_objects($type = 'all')
205
-    {
206
-        self::_set_autoloader();
207
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
208
-        return array(
209
-            'messenger' => $message_resource_manager->installed_messengers(),
210
-            'message_type' => $message_resource_manager->installed_message_types()
211
-        );
212
-    }
213
-
214
-
215
-    /**
216
-     * This will return an array of shortcodes => labels from the
217
-     * messenger and message_type objects associated with this
218
-     * template.
219
-     *
220
-     * @param string $message_type
221
-     * @param string $messenger
222
-     * @param array  $fields                        What fields we're returning valid shortcodes for.
223
-     *                                              If empty then we assume all fields are to be returned. Optional.
224
-     * @param string $context                       What context we're going to return shortcodes for. Optional.
225
-     * @param bool   $merged                        If TRUE then we don't return shortcodes indexed by field,
226
-     *                                              but instead an array of the unique shortcodes for all the given (
227
-     *                                              or all) fields. Optional.
228
-     * @return array                                an array of shortcodes in the format
229
-     *                                              array( '[shortcode] => 'label')
230
-     *                                              OR
231
-     *                                              FALSE if no shortcodes found.
232
-     * @throws ReflectionException
233
-     * @throws EE_Error*@since 4.3.0
234
-     *
235
-     */
236
-    public static function get_shortcodes(
237
-        $message_type,
238
-        $messenger,
239
-        $fields = array(),
240
-        $context = 'admin',
241
-        $merged = false
242
-    ) {
243
-        $messenger_name = str_replace(' ', '_', ucwords(str_replace('_', ' ', $messenger)));
244
-        $mt_name = str_replace(' ', '_', ucwords(str_replace('_', ' ', $message_type)));
245
-        /** @var EE_Message_Resource_Manager $message_resource_manager */
246
-        $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
247
-        // convert slug to object
248
-        $messenger = $message_resource_manager->get_messenger($messenger);
249
-
250
-        // if messenger isn't a EE_messenger resource then bail.
251
-        if (! $messenger instanceof EE_messenger) {
252
-            return array();
253
-        }
254
-
255
-        // validate class for getting our list of shortcodes
256
-        $classname = 'EE_Messages_' . $messenger_name . '_' . $mt_name . '_Validator';
257
-        if (! class_exists($classname)) {
258
-            $msg[] = esc_html__('The Validator class was unable to load', 'event_espresso');
259
-            $msg[] = sprintf(
260
-                esc_html__('The class name compiled was %s. Please check and make sure the spelling and case is correct for the class name and that there is an autoloader in place for this class', 'event_espresso'),
261
-                $classname
262
-            );
263
-            throw new EE_Error(implode('||', $msg));
264
-        }
265
-
266
-        /** @type EE_Messages_Validator $_VLD */
267
-        $_VLD = new $classname(array(), $context);
268
-        $valid_shortcodes = $_VLD->get_validators();
269
-
270
-        // let's make sure we're only getting the shortcode part of the validators
271
-        $shortcodes = array();
272
-        foreach ($valid_shortcodes as $field => $validators) {
273
-            $shortcodes[ $field ] = $validators['shortcodes'];
274
-        }
275
-        $valid_shortcodes = $shortcodes;
276
-
277
-        // if not all fields let's make sure we ONLY include the shortcodes for the specified fields.
278
-        if (! empty($fields)) {
279
-            $specified_shortcodes = array();
280
-            foreach ($fields as $field) {
281
-                if (isset($valid_shortcodes[ $field ])) {
282
-                    $specified_shortcodes[ $field ] = $valid_shortcodes[ $field ];
283
-                }
284
-            }
285
-            $valid_shortcodes = $specified_shortcodes;
286
-        }
287
-
288
-        // if not merged then let's replace the fields with the localized fields
289
-        if (! $merged) {
290
-            // let's get all the fields for the set messenger so that we can get the localized label and use that in the returned array.
291
-            $field_settings = $messenger->get_template_fields();
292
-            $localized = array();
293
-            foreach ($valid_shortcodes as $field => $shortcodes) {
294
-                // get localized field label
295
-                if (isset($field_settings[ $field ])) {
296
-                    // possible that this is used as a main field.
297
-                    if (empty($field_settings[ $field ])) {
298
-                        if (isset($field_settings['extra'][ $field ])) {
299
-                            $_field = $field_settings['extra'][ $field ]['main']['label'];
300
-                        } else {
301
-                            $_field = $field;
302
-                        }
303
-                    } else {
304
-                        $_field = $field_settings[ $field ]['label'];
305
-                    }
306
-                } elseif (isset($field_settings['extra'])) {
307
-                    // loop through extra "main fields" and see if any of their children have our field
308
-                    foreach ($field_settings['extra'] as $fields) {
309
-                        if (isset($fields[ $field ])) {
310
-                            $_field = $fields[ $field ]['label'];
311
-                        } else {
312
-                            $_field = $field;
313
-                        }
314
-                    }
315
-                } else {
316
-                    $_field = $field;
317
-                }
318
-                if (isset($_field)) {
319
-                    $localized[ (string) $_field ] = $shortcodes;
320
-                }
321
-            }
322
-            $valid_shortcodes = $localized;
323
-        }
324
-
325
-        // if $merged then let's merge all the shortcodes into one list NOT indexed by field.
326
-        if ($merged) {
327
-            $merged_codes = array();
328
-            foreach ($valid_shortcodes as $shortcode) {
329
-                foreach ($shortcode as $code => $label) {
330
-                    if (isset($merged_codes[ $code ])) {
331
-                        continue;
332
-                    } else {
333
-                        $merged_codes[ $code ] = $label;
334
-                    }
335
-                }
336
-            }
337
-            $valid_shortcodes = $merged_codes;
338
-        }
339
-
340
-        return $valid_shortcodes;
341
-    }
342
-
343
-
344
-    /**
345
-     * Get Messenger object.
346
-     *
347
-     * @param string $messenger messenger slug for the messenger object we want to retrieve.
348
-     * @return EE_messenger
349
-     * @throws ReflectionException
350
-     * @throws EE_Error*@since 4.3.0
351
-     * @deprecated 4.9.0
352
-     */
353
-    public static function messenger_obj($messenger)
354
-    {
355
-        /** @type EE_Message_Resource_Manager $Message_Resource_Manager */
356
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
357
-        return $Message_Resource_Manager->get_messenger($messenger);
358
-    }
359
-
360
-
361
-    /**
362
-     * get Message type object
363
-     *
364
-     * @param string $message_type the slug for the message type object to retrieve
365
-     * @return EE_message_type
366
-     * @throws ReflectionException
367
-     * @throws EE_Error*@since 4.3.0
368
-     * @deprecated 4.9.0
369
-     */
370
-    public static function message_type_obj($message_type)
371
-    {
372
-        /** @type EE_Message_Resource_Manager $Message_Resource_Manager */
373
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
374
-        return $Message_Resource_Manager->get_message_type($message_type);
375
-    }
376
-
377
-
378
-    /**
379
-     * Given a message_type slug, will return whether that message type is active in the system or not.
380
-     *
381
-     * @since    4.3.0
382
-     * @param string $message_type message type to check for.
383
-     * @return boolean
384
-     * @throws EE_Error
385
-     * @throws ReflectionException
386
-     */
387
-    public static function is_mt_active($message_type)
388
-    {
389
-        /** @type EE_Message_Resource_Manager $Message_Resource_Manager */
390
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
391
-        $active_mts = $Message_Resource_Manager->list_of_active_message_types();
392
-        return in_array($message_type, $active_mts);
393
-    }
394
-
395
-
396
-    /**
397
-     * Given a messenger slug, will return whether that messenger is active in the system or not.
398
-     *
399
-     * @since    4.3.0
400
-     *
401
-     * @param string $messenger slug for messenger to check.
402
-     * @return boolean
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     */
406
-    public static function is_messenger_active($messenger)
407
-    {
408
-        /** @type EE_Message_Resource_Manager $Message_Resource_Manager */
409
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
410
-        $active_messenger = $Message_Resource_Manager->get_active_messenger($messenger);
411
-        return $active_messenger instanceof EE_messenger;
412
-    }
413
-
414
-
415
-    /**
416
-     * Used to return active messengers array stored in the wp options table.
417
-     * If no value is present in the option then an empty array is returned.
418
-     *
419
-     * @deprecated 4.9
420
-     * @since      4.3.1
421
-     *
422
-     * @return array
423
-     * @throws EE_Error
424
-     * @throws ReflectionException
425
-     */
426
-    public static function get_active_messengers_in_db()
427
-    {
428
-        EE_Error::doing_it_wrong(
429
-            __METHOD__,
430
-            esc_html__('Please use EE_Message_Resource_Manager::get_active_messengers_option() instead.', 'event_espresso'),
431
-            '4.9.0'
432
-        );
433
-        /** @var EE_Message_Resource_Manager $Message_Resource_Manager */
434
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
435
-        return $Message_Resource_Manager->get_active_messengers_option();
436
-    }
437
-
438
-
439
-    /**
440
-     * Used to update the active messengers array stored in the wp options table.
441
-     *
442
-     * @since      4.3.1
443
-     * @deprecated 4.9.0
444
-     *
445
-     * @param array $data_to_save Incoming data to save.
446
-     *
447
-     * @return bool FALSE if not updated, TRUE if updated.
448
-     * @throws EE_Error
449
-     * @throws ReflectionException
450
-     */
451
-    public static function update_active_messengers_in_db($data_to_save)
452
-    {
453
-        EE_Error::doing_it_wrong(
454
-            __METHOD__,
455
-            esc_html__('Please use EE_Message_Resource_Manager::update_active_messengers_option() instead.', 'event_espresso'),
456
-            '4.9.0'
457
-        );
458
-        /** @var EE_Message_Resource_Manager $Message_Resource_Manager */
459
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
460
-        return $Message_Resource_Manager->update_active_messengers_option($data_to_save);
461
-    }
462
-
463
-
464
-    /**
465
-     * This does some validation of incoming params, determines what type of url is being prepped and returns the
466
-     * appropriate url trigger
467
-     *
468
-     * @param EE_message_type $message_type
469
-     * @param EE_Message $message
470
-     * @param EE_Registration | null $registration  The registration object must be included if this
471
-     *                                              is going to be a registration trigger url.
472
-     * @param string $sending_messenger             The (optional) sending messenger for the url.
473
-     *
474
-     * @return string
475
-     * @throws EE_Error
476
-     */
477
-    public static function get_url_trigger(
478
-        EE_message_type $message_type,
479
-        EE_Message $message,
480
-        $registration = null,
481
-        $sending_messenger = ''
482
-    ) {
483
-        // first determine if the url can be to the EE_Message object.
484
-        if (! $message_type->always_generate()) {
485
-            return EEH_MSG_Template::generate_browser_trigger($message);
486
-        }
487
-
488
-        // if $registration object is not valid then exit early because there's nothing that can be generated.
489
-        if (! $registration instanceof EE_Registration) {
490
-            throw new EE_Error(
491
-                esc_html__('Incoming value for registration is not a valid EE_Registration object.', 'event_espresso')
492
-            );
493
-        }
494
-
495
-        // validate given context
496
-        $contexts = $message_type->get_contexts();
497
-        if ($message->context() !== '' && ! isset($contexts[ $message->context() ])) {
498
-            throw new EE_Error(
499
-                sprintf(
500
-                    esc_html__('The context %s is not a valid context for %s.', 'event_espresso'),
501
-                    $message->context(),
502
-                    get_class($message_type)
503
-                )
504
-            );
505
-        }
506
-
507
-        // valid sending messenger but only if sending messenger set.  Otherwise generating messenger is used.
508
-        if (! empty($sending_messenger)) {
509
-            $with_messengers = $message_type->with_messengers();
510
-            if (
511
-                ! isset($with_messengers[ $message->messenger() ])
512
-                 || ! in_array($sending_messenger, $with_messengers[ $message->messenger() ])
513
-            ) {
514
-                throw new EE_Error(
515
-                    sprintf(
516
-                        esc_html__(
517
-                            'The given sending messenger string (%1$s) does not match a valid sending messenger with the %2$s.  If this is incorrect, make sure that the message type has defined this messenger as a sending messenger in its $_with_messengers array.',
518
-                            'event_espresso'
519
-                        ),
520
-                        $sending_messenger,
521
-                        get_class($message_type)
522
-                    )
523
-                );
524
-            }
525
-        } else {
526
-            $sending_messenger = $message->messenger();
527
-        }
528
-        return EEH_MSG_Template::generate_url_trigger(
529
-            $sending_messenger,
530
-            $message->messenger(),
531
-            $message->context(),
532
-            $message->message_type(),
533
-            $registration,
534
-            $message->GRP_ID()
535
-        );
536
-    }
537
-
538
-
539
-    /**
540
-     * This returns the url for triggering a in browser view of a specific EE_Message object.
541
-     * @param EE_Message $message
542
-     * @return string.
543
-     */
544
-    public static function generate_browser_trigger(EE_Message $message)
545
-    {
546
-        $query_args = array(
547
-            'ee' => 'msg_browser_trigger',
548
-            'token' => $message->MSG_token()
549
-        );
550
-        return apply_filters(
551
-            'FHEE__EEH_MSG_Template__generate_browser_trigger',
552
-            add_query_arg($query_args, site_url()),
553
-            $message
554
-        );
555
-    }
556
-
557
-
558
-
559
-
560
-
561
-
562
-    /**
563
-     * This returns the url for triggering an in browser view of the error saved on the incoming message object.
564
-     * @param EE_Message $message
565
-     * @return string
566
-     */
567
-    public static function generate_error_display_trigger(EE_Message $message)
568
-    {
569
-        return apply_filters(
570
-            'FHEE__EEH_MSG_Template__generate_error_display_trigger',
571
-            add_query_arg(
572
-                array(
573
-                    'ee' => 'msg_browser_error_trigger',
574
-                    'token' => $message->MSG_token()
575
-                ),
576
-                site_url()
577
-            ),
578
-            $message
579
-        );
580
-    }
581
-
582
-
583
-    /**
584
-     * This generates a url trigger for the msg_url_trigger route using the given arguments
585
-     *
586
-     * @param string          $sending_messenger      The sending messenger slug.
587
-     * @param string          $generating_messenger   The generating messenger slug.
588
-     * @param string          $context                The context for the template.
589
-     * @param string          $message_type           The message type slug
590
-     * @param EE_Registration $registration
591
-     * @param integer         $message_template_group id   The EE_Message_Template_Group ID for the template.
592
-     * @param integer         $data_id                The id to the EE_Base_Class for getting the data used by the
593
-     *                                                trigger.
594
-     * @return string          The generated url.
595
-     * @throws EE_Error
596
-     */
597
-    public static function generate_url_trigger(
598
-        $sending_messenger,
599
-        $generating_messenger,
600
-        $context,
601
-        $message_type,
602
-        EE_Registration $registration,
603
-        $message_template_group,
604
-        $data_id = 0
605
-    ) {
606
-        $query_args = array(
607
-            'ee' => 'msg_url_trigger',
608
-            'snd_msgr' => $sending_messenger,
609
-            'gen_msgr' => $generating_messenger,
610
-            'message_type' => $message_type,
611
-            'context' => $context,
612
-            'token' => $registration->reg_url_link(),
613
-            'GRP_ID' => $message_template_group,
614
-            'id' => $data_id
615
-            );
616
-        $url = add_query_arg($query_args, get_home_url());
617
-
618
-        // made it here so now we can just get the url and filter it.  Filtered globally and by message type.
619
-        return apply_filters(
620
-            'FHEE__EEH_MSG_Template__generate_url_trigger',
621
-            $url,
622
-            $sending_messenger,
623
-            $generating_messenger,
624
-            $context,
625
-            $message_type,
626
-            $registration,
627
-            $message_template_group,
628
-            $data_id
629
-        );
630
-    }
631
-
632
-
633
-
634
-
635
-    /**
636
-     * Return the specific css for the action icon given.
637
-     *
638
-     * @param string $type  What action to return.
639
-     * @return string[]
640
-     * @since 4.9.0
641
-     */
642
-    public static function get_message_action_icon($type)
643
-    {
644
-        $action_icons = self::get_message_action_icons();
645
-        return isset($action_icons[ $type ]) ? $action_icons[ $type ] : [];
646
-    }
647
-
648
-
649
-    /**
650
-     * This is used for retrieving the css classes used for the icons representing message actions.
651
-     *
652
-     * @since 4.9.0
653
-     *
654
-     * @return array
655
-     */
656
-    public static function get_message_action_icons()
657
-    {
658
-        return apply_filters(
659
-            'FHEE__EEH_MSG_Template__message_action_icons',
660
-            array(
661
-                'view' => array(
662
-                    'label' => esc_html__('View Message', 'event_espresso'),
663
-                    'css_class' => 'dashicons dashicons-visibility',
664
-                ),
665
-                'error' => array(
666
-                    'label' => esc_html__('View Error Message', 'event_espresso'),
667
-                    'css_class' => 'dashicons dashicons-info',
668
-                ),
669
-                'see_notifications_for' => array(
670
-                    'label' => esc_html__('View Related Messages', 'event_espresso'),
671
-                    'css_class' => 'dashicons dashicons-megaphone',
672
-                ),
673
-                'generate_now' => array(
674
-                    'label' => esc_html__('Generate the message now.', 'event_espresso'),
675
-                    'css_class' => 'dashicons dashicons-admin-tools',
676
-                ),
677
-                'send_now' => array(
678
-                    'label' => esc_html__('Send Immediately', 'event_espresso'),
679
-                    'css_class' => 'dashicons dashicons-controls-forward',
680
-                ),
681
-                'queue_for_resending' => array(
682
-                    'label' => esc_html__('Queue for Resending', 'event_espresso'),
683
-                    'css_class' => 'dashicons dashicons-controls-repeat',
684
-                ),
685
-                'view_transaction' => array(
686
-                    'label' => esc_html__('View related Transaction', 'event_espresso'),
687
-                    'css_class' => 'dashicons dashicons-cart',
688
-                )
689
-            )
690
-        );
691
-    }
692
-
693
-
694
-    /**
695
-     * This returns the url for a given action related to EE_Message.
696
-     *
697
-     * @param string     $type         What type of action to return the url for.
698
-     * @param EE_Message $message      Required for generating the correct url for some types.
699
-     * @param array      $query_params Any additional query params to be included with the generated url.
700
-     *
701
-     * @return string
702
-     * @throws EE_Error
703
-     * @throws ReflectionException
704
-     * @since 4.9.0
705
-     *
706
-     */
707
-    public static function get_message_action_url($type, EE_Message $message = null, $query_params = array())
708
-    {
709
-        $action_urls = self::get_message_action_urls($message, $query_params);
710
-        return isset($action_urls[ $type ])  ? $action_urls[ $type ] : '';
711
-    }
712
-
713
-
714
-    /**
715
-     * This returns all the current urls for EE_Message actions.
716
-     *
717
-     * @since 4.9.0
718
-     *
719
-     * @param EE_Message $message      The EE_Message object required to generate correct urls for some types.
720
-     * @param array      $query_params Any additional query_params to be included with the generated url.
721
-     *
722
-     * @return array
723
-     * @throws EE_Error
724
-     * @throws ReflectionException
725
-     */
726
-    public static function get_message_action_urls(EE_Message $message = null, $query_params = array())
727
-    {
728
-        EE_Registry::instance()->load_helper('URL');
729
-        // if $message is not an instance of EE_Message then let's just do a dummy.
730
-        $message = empty($message) ? EE_Message_Factory::create() : $message;
731
-        $action_urls =  apply_filters(
732
-            'FHEE__EEH_MSG_Template__get_message_action_url',
733
-            array(
734
-                'view' => EEH_MSG_Template::generate_browser_trigger($message),
735
-                'error' => EEH_MSG_Template::generate_error_display_trigger($message),
736
-                'see_notifications_for' => EEH_URL::add_query_args_and_nonce(
737
-                    array_merge(
738
-                        array(
739
-                            'page' => 'espresso_messages',
740
-                            'action' => 'default',
741
-                            'filterby' => 1,
742
-                        ),
743
-                        $query_params
744
-                    ),
745
-                    admin_url('admin.php')
746
-                ),
747
-                'generate_now' => EEH_URL::add_query_args_and_nonce(
748
-                    array(
749
-                        'page' => 'espresso_messages',
750
-                        'action' => 'generate_now',
751
-                        'MSG_ID' => $message->ID()
752
-                    ),
753
-                    admin_url('admin.php')
754
-                ),
755
-                'send_now' => EEH_URL::add_query_args_and_nonce(
756
-                    array(
757
-                        'page' => 'espresso_messages',
758
-                        'action' => 'send_now',
759
-                        'MSG_ID' => $message->ID()
760
-                    ),
761
-                    admin_url('admin.php')
762
-                ),
763
-                'queue_for_resending' => EEH_URL::add_query_args_and_nonce(
764
-                    array(
765
-                        'page' => 'espresso_messages',
766
-                        'action' => 'queue_for_resending',
767
-                        'MSG_ID' => $message->ID()
768
-                    ),
769
-                    admin_url('admin.php')
770
-                ),
771
-            )
772
-        );
773
-        if (
774
-            $message->TXN_ID() > 0
775
-            && EE_Registry::instance()->CAP->current_user_can(
776
-                'ee_read_transaction',
777
-                'espresso_transactions_default',
778
-                $message->TXN_ID()
779
-            )
780
-        ) {
781
-            $action_urls['view_transaction'] = EEH_URL::add_query_args_and_nonce(
782
-                array(
783
-                    'page' => 'espresso_transactions',
784
-                    'action' => 'view_transaction',
785
-                    'TXN_ID' => $message->TXN_ID()
786
-                ),
787
-                admin_url('admin.php')
788
-            );
789
-        } else {
790
-            $action_urls['view_transaction'] = '';
791
-        }
792
-        return $action_urls;
793
-    }
794
-
795
-
796
-    /**
797
-     * This returns a generated link html including the icon used for the action link for EE_Message actions.
798
-     *
799
-     * @param string          $type         What type of action the link is for (if invalid type is passed in then an
800
-     *                                      empty string is returned)
801
-     * @param EE_Message|null $message      The EE_Message object (required for some actions to generate correctly)
802
-     * @param array           $query_params Any extra query params to include in the generated link.
803
-     *
804
-     * @return string
805
-     * @throws EE_Error
806
-     * @throws ReflectionException
807
-     * @since 4.9.0
808
-     *
809
-     */
810
-    public static function get_message_action_link($type, EE_Message $message = null, $query_params = array())
811
-    {
812
-        $url = EEH_MSG_Template::get_message_action_url($type, $message, $query_params);
813
-        $icon_css = EEH_MSG_Template::get_message_action_icon($type);
814
-        $label = $icon_css['label'] ?? null;
815
-        $label = $label ? 'aria-label="' . $label . '"' : '';
816
-        $class = $label ? ' ee-aria-tooltip' : '';
817
-
818
-        if (empty($url) || empty($icon_css) || ! isset($icon_css['css_class'])) {
819
-            return '';
820
-        }
821
-
822
-        $icon_css_class = $icon_css['css_class'] . apply_filters(
823
-            'FHEE__EEH_MSG_Template__get_message_action_link__icon_css_class',
824
-            ' js-ee-message-action-link ee-message-action-link-' . $type,
825
-            $type,
826
-            $message,
827
-            $query_params
828
-        );
829
-
830
-        return '
17
+	/**
18
+	 * Holds a collection of EE_Message_Template_Pack objects.
19
+	 * @type EE_Messages_Template_Pack_Collection
20
+	 */
21
+	protected static $_template_pack_collection;
22
+
23
+
24
+	/**
25
+	 * @throws EE_Error
26
+	 */
27
+	private static function _set_autoloader()
28
+	{
29
+		EED_Messages::set_autoloaders();
30
+	}
31
+
32
+
33
+	/**
34
+	 * generate_new_templates
35
+	 * This will handle the messenger, message_type selection when "adding a new custom template" for an event and will
36
+	 * automatically create the defaults for the event.  The user would then be redirected to edit the default context
37
+	 * for the event.
38
+	 *
39
+	 * @access protected
40
+	 * @param string $messenger     the messenger we are generating templates for
41
+	 * @param array  $message_types array of message types that the templates are generated for.
42
+	 * @param int    $GRP_ID        If a non global template is being generated then it is expected we'll have a GRP_ID
43
+	 *                              to use as the base for the new generated template.
44
+	 * @param bool   $global        true indicates generating templates on messenger activation. false requires GRP_ID
45
+	 *                              for event specific template generation.
46
+	 * @return array  @see EEH_MSG_Template::_create_new_templates for the return value of each element in the array
47
+	 *                for templates that are generated.  If this is an empty array then it means no templates were
48
+	 *                generated which usually means there was an error.  Anything in the array with an empty value for
49
+	 *                `MTP_context` means that it was not a new generated template but just reactivated (which only
50
+	 *                happens for global templates that already exist in the database.
51
+	 * @throws EE_Error
52
+	 * @throws ReflectionException
53
+	 */
54
+	public static function generate_new_templates($messenger, $message_types, $GRP_ID = 0, $global = false)
55
+	{
56
+		// make sure message_type is an array.
57
+		$message_types = (array) $message_types;
58
+		$templates = array();
59
+
60
+		if (empty($messenger)) {
61
+			throw new EE_Error(esc_html__('We need a messenger to generate templates!', 'event_espresso'));
62
+		}
63
+
64
+		// if we STILL have empty $message_types then we need to generate an error message b/c we NEED message types to do the template files.
65
+		if (empty($message_types)) {
66
+			throw new EE_Error(esc_html__('We need at least one message type to generate templates!', 'event_espresso'));
67
+		}
68
+
69
+		EEH_MSG_Template::_set_autoloader();
70
+		foreach ($message_types as $message_type) {
71
+			// if this is global template generation.
72
+			if ($global) {
73
+				// let's attempt to get the GRP_ID for this combo IF GRP_ID is empty.
74
+				if (empty($GRP_ID)) {
75
+					$GRP_ID = EEM_Message_Template_Group::instance()->get_one(
76
+						array(
77
+							array(
78
+								'MTP_messenger'    => $messenger,
79
+								'MTP_message_type' => $message_type,
80
+								'MTP_is_global'    => true,
81
+							),
82
+						)
83
+					);
84
+					$GRP_ID = $GRP_ID instanceof EE_Message_Template_Group ? $GRP_ID->ID() : 0;
85
+				}
86
+				// First let's determine if we already HAVE global templates for this messenger and message_type combination.
87
+				//  If we do then NO generation!!
88
+				if (EEH_MSG_Template::already_generated($messenger, $message_type, $GRP_ID)) {
89
+					$templates[] = array(
90
+						'GRP_ID' => $GRP_ID,
91
+						'MTP_context' => '',
92
+					);
93
+					// we already have generated templates for this so let's go to the next message type.
94
+					continue;
95
+				}
96
+			}
97
+			$new_message_template_group = EEH_MSG_Template::create_new_templates(
98
+				$messenger,
99
+				$message_type,
100
+				$GRP_ID,
101
+				$global
102
+			);
103
+
104
+			if (! $new_message_template_group) {
105
+				continue;
106
+			}
107
+			$templates[] = $new_message_template_group;
108
+		}
109
+
110
+		return $templates;
111
+	}
112
+
113
+
114
+	/**
115
+	 * The purpose of this method is to determine if there are already generated templates in the database for the
116
+	 * given variables.
117
+	 *
118
+	 * @param string $messenger    messenger
119
+	 * @param string $message_type message type
120
+	 * @param int    $GRP_ID       GRP ID ( if a custom template) (if not provided then we're just doing global
121
+	 *                             template check)
122
+	 * @return bool                true = generated, false = hasn't been generated.
123
+	 * @throws EE_Error
124
+	 */
125
+	public static function already_generated($messenger, $message_type, $GRP_ID = 0)
126
+	{
127
+		EEH_MSG_Template::_set_autoloader();
128
+		// what method we use depends on whether we have an GRP_ID or not
129
+		$count = empty($GRP_ID)
130
+			? EEM_Message_Template::instance()->count(
131
+				array(
132
+					array(
133
+						'Message_Template_Group.MTP_messenger'    => $messenger,
134
+						'Message_Template_Group.MTP_message_type' => $message_type,
135
+						'Message_Template_Group.MTP_is_global'    => true
136
+					)
137
+				)
138
+			)
139
+			: EEM_Message_Template::instance()->count(array( array( 'GRP_ID' => $GRP_ID ) ));
140
+
141
+		return $count > 0;
142
+	}
143
+
144
+
145
+	/**
146
+	 * Updates all message templates matching the incoming messengers and message types to active status.
147
+	 *
148
+	 * @static
149
+	 * @param array $messenger_names    Messenger slug
150
+	 * @param array $message_type_names Message type slug
151
+	 * @return  int                         count of updated records.
152
+	 * @throws EE_Error
153
+	 */
154
+	public static function update_to_active($messenger_names, $message_type_names)
155
+	{
156
+		$messenger_names = is_array($messenger_names) ? $messenger_names : array( $messenger_names );
157
+		$message_type_names = is_array($message_type_names) ? $message_type_names : array( $message_type_names );
158
+		return EEM_Message_Template_Group::instance()->update(
159
+			array( 'MTP_is_active' => 1 ),
160
+			array(
161
+				array(
162
+					'MTP_messenger'     => array( 'IN', $messenger_names ),
163
+					'MTP_message_type'  => array( 'IN', $message_type_names )
164
+				)
165
+			)
166
+		);
167
+	}
168
+
169
+
170
+	/**
171
+	 * Updates all message template groups matching the incoming arguments to inactive status.
172
+	 *
173
+	 * @static
174
+	 * @param array $messenger_names    The messenger slugs.
175
+	 *                                  If empty then all templates matching the message types are marked inactive.
176
+	 *                                  Otherwise only templates matching the messengers and message types.
177
+	 * @param array $message_type_names The message type slugs.
178
+	 *                                  If empty then all templates matching the messengers are marked inactive.
179
+	 *                                  Otherwise only templates matching the messengers and message types.
180
+	 *
181
+	 * @return int  count of updated records.
182
+	 * @throws EE_Error
183
+	 */
184
+	public static function update_to_inactive($messenger_names = array(), $message_type_names = array())
185
+	{
186
+		return EEM_Message_Template_Group::instance()->deactivate_message_template_groups_for(
187
+			$messenger_names,
188
+			$message_type_names
189
+		);
190
+	}
191
+
192
+
193
+	/**
194
+	 * The purpose of this function is to return all installed message objects
195
+	 * (messengers and message type regardless of whether they are ACTIVE or not)
196
+	 *
197
+	 * @param string $type
198
+	 * @return array array consisting of installed messenger objects and installed message type objects.
199
+	 * @throws EE_Error
200
+	 * @throws ReflectionException
201
+	 * @deprecated 4.9.0
202
+	 * @static
203
+	 */
204
+	public static function get_installed_message_objects($type = 'all')
205
+	{
206
+		self::_set_autoloader();
207
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
208
+		return array(
209
+			'messenger' => $message_resource_manager->installed_messengers(),
210
+			'message_type' => $message_resource_manager->installed_message_types()
211
+		);
212
+	}
213
+
214
+
215
+	/**
216
+	 * This will return an array of shortcodes => labels from the
217
+	 * messenger and message_type objects associated with this
218
+	 * template.
219
+	 *
220
+	 * @param string $message_type
221
+	 * @param string $messenger
222
+	 * @param array  $fields                        What fields we're returning valid shortcodes for.
223
+	 *                                              If empty then we assume all fields are to be returned. Optional.
224
+	 * @param string $context                       What context we're going to return shortcodes for. Optional.
225
+	 * @param bool   $merged                        If TRUE then we don't return shortcodes indexed by field,
226
+	 *                                              but instead an array of the unique shortcodes for all the given (
227
+	 *                                              or all) fields. Optional.
228
+	 * @return array                                an array of shortcodes in the format
229
+	 *                                              array( '[shortcode] => 'label')
230
+	 *                                              OR
231
+	 *                                              FALSE if no shortcodes found.
232
+	 * @throws ReflectionException
233
+	 * @throws EE_Error*@since 4.3.0
234
+	 *
235
+	 */
236
+	public static function get_shortcodes(
237
+		$message_type,
238
+		$messenger,
239
+		$fields = array(),
240
+		$context = 'admin',
241
+		$merged = false
242
+	) {
243
+		$messenger_name = str_replace(' ', '_', ucwords(str_replace('_', ' ', $messenger)));
244
+		$mt_name = str_replace(' ', '_', ucwords(str_replace('_', ' ', $message_type)));
245
+		/** @var EE_Message_Resource_Manager $message_resource_manager */
246
+		$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
247
+		// convert slug to object
248
+		$messenger = $message_resource_manager->get_messenger($messenger);
249
+
250
+		// if messenger isn't a EE_messenger resource then bail.
251
+		if (! $messenger instanceof EE_messenger) {
252
+			return array();
253
+		}
254
+
255
+		// validate class for getting our list of shortcodes
256
+		$classname = 'EE_Messages_' . $messenger_name . '_' . $mt_name . '_Validator';
257
+		if (! class_exists($classname)) {
258
+			$msg[] = esc_html__('The Validator class was unable to load', 'event_espresso');
259
+			$msg[] = sprintf(
260
+				esc_html__('The class name compiled was %s. Please check and make sure the spelling and case is correct for the class name and that there is an autoloader in place for this class', 'event_espresso'),
261
+				$classname
262
+			);
263
+			throw new EE_Error(implode('||', $msg));
264
+		}
265
+
266
+		/** @type EE_Messages_Validator $_VLD */
267
+		$_VLD = new $classname(array(), $context);
268
+		$valid_shortcodes = $_VLD->get_validators();
269
+
270
+		// let's make sure we're only getting the shortcode part of the validators
271
+		$shortcodes = array();
272
+		foreach ($valid_shortcodes as $field => $validators) {
273
+			$shortcodes[ $field ] = $validators['shortcodes'];
274
+		}
275
+		$valid_shortcodes = $shortcodes;
276
+
277
+		// if not all fields let's make sure we ONLY include the shortcodes for the specified fields.
278
+		if (! empty($fields)) {
279
+			$specified_shortcodes = array();
280
+			foreach ($fields as $field) {
281
+				if (isset($valid_shortcodes[ $field ])) {
282
+					$specified_shortcodes[ $field ] = $valid_shortcodes[ $field ];
283
+				}
284
+			}
285
+			$valid_shortcodes = $specified_shortcodes;
286
+		}
287
+
288
+		// if not merged then let's replace the fields with the localized fields
289
+		if (! $merged) {
290
+			// let's get all the fields for the set messenger so that we can get the localized label and use that in the returned array.
291
+			$field_settings = $messenger->get_template_fields();
292
+			$localized = array();
293
+			foreach ($valid_shortcodes as $field => $shortcodes) {
294
+				// get localized field label
295
+				if (isset($field_settings[ $field ])) {
296
+					// possible that this is used as a main field.
297
+					if (empty($field_settings[ $field ])) {
298
+						if (isset($field_settings['extra'][ $field ])) {
299
+							$_field = $field_settings['extra'][ $field ]['main']['label'];
300
+						} else {
301
+							$_field = $field;
302
+						}
303
+					} else {
304
+						$_field = $field_settings[ $field ]['label'];
305
+					}
306
+				} elseif (isset($field_settings['extra'])) {
307
+					// loop through extra "main fields" and see if any of their children have our field
308
+					foreach ($field_settings['extra'] as $fields) {
309
+						if (isset($fields[ $field ])) {
310
+							$_field = $fields[ $field ]['label'];
311
+						} else {
312
+							$_field = $field;
313
+						}
314
+					}
315
+				} else {
316
+					$_field = $field;
317
+				}
318
+				if (isset($_field)) {
319
+					$localized[ (string) $_field ] = $shortcodes;
320
+				}
321
+			}
322
+			$valid_shortcodes = $localized;
323
+		}
324
+
325
+		// if $merged then let's merge all the shortcodes into one list NOT indexed by field.
326
+		if ($merged) {
327
+			$merged_codes = array();
328
+			foreach ($valid_shortcodes as $shortcode) {
329
+				foreach ($shortcode as $code => $label) {
330
+					if (isset($merged_codes[ $code ])) {
331
+						continue;
332
+					} else {
333
+						$merged_codes[ $code ] = $label;
334
+					}
335
+				}
336
+			}
337
+			$valid_shortcodes = $merged_codes;
338
+		}
339
+
340
+		return $valid_shortcodes;
341
+	}
342
+
343
+
344
+	/**
345
+	 * Get Messenger object.
346
+	 *
347
+	 * @param string $messenger messenger slug for the messenger object we want to retrieve.
348
+	 * @return EE_messenger
349
+	 * @throws ReflectionException
350
+	 * @throws EE_Error*@since 4.3.0
351
+	 * @deprecated 4.9.0
352
+	 */
353
+	public static function messenger_obj($messenger)
354
+	{
355
+		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
356
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
357
+		return $Message_Resource_Manager->get_messenger($messenger);
358
+	}
359
+
360
+
361
+	/**
362
+	 * get Message type object
363
+	 *
364
+	 * @param string $message_type the slug for the message type object to retrieve
365
+	 * @return EE_message_type
366
+	 * @throws ReflectionException
367
+	 * @throws EE_Error*@since 4.3.0
368
+	 * @deprecated 4.9.0
369
+	 */
370
+	public static function message_type_obj($message_type)
371
+	{
372
+		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
373
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
374
+		return $Message_Resource_Manager->get_message_type($message_type);
375
+	}
376
+
377
+
378
+	/**
379
+	 * Given a message_type slug, will return whether that message type is active in the system or not.
380
+	 *
381
+	 * @since    4.3.0
382
+	 * @param string $message_type message type to check for.
383
+	 * @return boolean
384
+	 * @throws EE_Error
385
+	 * @throws ReflectionException
386
+	 */
387
+	public static function is_mt_active($message_type)
388
+	{
389
+		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
390
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
391
+		$active_mts = $Message_Resource_Manager->list_of_active_message_types();
392
+		return in_array($message_type, $active_mts);
393
+	}
394
+
395
+
396
+	/**
397
+	 * Given a messenger slug, will return whether that messenger is active in the system or not.
398
+	 *
399
+	 * @since    4.3.0
400
+	 *
401
+	 * @param string $messenger slug for messenger to check.
402
+	 * @return boolean
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 */
406
+	public static function is_messenger_active($messenger)
407
+	{
408
+		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
409
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
410
+		$active_messenger = $Message_Resource_Manager->get_active_messenger($messenger);
411
+		return $active_messenger instanceof EE_messenger;
412
+	}
413
+
414
+
415
+	/**
416
+	 * Used to return active messengers array stored in the wp options table.
417
+	 * If no value is present in the option then an empty array is returned.
418
+	 *
419
+	 * @deprecated 4.9
420
+	 * @since      4.3.1
421
+	 *
422
+	 * @return array
423
+	 * @throws EE_Error
424
+	 * @throws ReflectionException
425
+	 */
426
+	public static function get_active_messengers_in_db()
427
+	{
428
+		EE_Error::doing_it_wrong(
429
+			__METHOD__,
430
+			esc_html__('Please use EE_Message_Resource_Manager::get_active_messengers_option() instead.', 'event_espresso'),
431
+			'4.9.0'
432
+		);
433
+		/** @var EE_Message_Resource_Manager $Message_Resource_Manager */
434
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
435
+		return $Message_Resource_Manager->get_active_messengers_option();
436
+	}
437
+
438
+
439
+	/**
440
+	 * Used to update the active messengers array stored in the wp options table.
441
+	 *
442
+	 * @since      4.3.1
443
+	 * @deprecated 4.9.0
444
+	 *
445
+	 * @param array $data_to_save Incoming data to save.
446
+	 *
447
+	 * @return bool FALSE if not updated, TRUE if updated.
448
+	 * @throws EE_Error
449
+	 * @throws ReflectionException
450
+	 */
451
+	public static function update_active_messengers_in_db($data_to_save)
452
+	{
453
+		EE_Error::doing_it_wrong(
454
+			__METHOD__,
455
+			esc_html__('Please use EE_Message_Resource_Manager::update_active_messengers_option() instead.', 'event_espresso'),
456
+			'4.9.0'
457
+		);
458
+		/** @var EE_Message_Resource_Manager $Message_Resource_Manager */
459
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
460
+		return $Message_Resource_Manager->update_active_messengers_option($data_to_save);
461
+	}
462
+
463
+
464
+	/**
465
+	 * This does some validation of incoming params, determines what type of url is being prepped and returns the
466
+	 * appropriate url trigger
467
+	 *
468
+	 * @param EE_message_type $message_type
469
+	 * @param EE_Message $message
470
+	 * @param EE_Registration | null $registration  The registration object must be included if this
471
+	 *                                              is going to be a registration trigger url.
472
+	 * @param string $sending_messenger             The (optional) sending messenger for the url.
473
+	 *
474
+	 * @return string
475
+	 * @throws EE_Error
476
+	 */
477
+	public static function get_url_trigger(
478
+		EE_message_type $message_type,
479
+		EE_Message $message,
480
+		$registration = null,
481
+		$sending_messenger = ''
482
+	) {
483
+		// first determine if the url can be to the EE_Message object.
484
+		if (! $message_type->always_generate()) {
485
+			return EEH_MSG_Template::generate_browser_trigger($message);
486
+		}
487
+
488
+		// if $registration object is not valid then exit early because there's nothing that can be generated.
489
+		if (! $registration instanceof EE_Registration) {
490
+			throw new EE_Error(
491
+				esc_html__('Incoming value for registration is not a valid EE_Registration object.', 'event_espresso')
492
+			);
493
+		}
494
+
495
+		// validate given context
496
+		$contexts = $message_type->get_contexts();
497
+		if ($message->context() !== '' && ! isset($contexts[ $message->context() ])) {
498
+			throw new EE_Error(
499
+				sprintf(
500
+					esc_html__('The context %s is not a valid context for %s.', 'event_espresso'),
501
+					$message->context(),
502
+					get_class($message_type)
503
+				)
504
+			);
505
+		}
506
+
507
+		// valid sending messenger but only if sending messenger set.  Otherwise generating messenger is used.
508
+		if (! empty($sending_messenger)) {
509
+			$with_messengers = $message_type->with_messengers();
510
+			if (
511
+				! isset($with_messengers[ $message->messenger() ])
512
+				 || ! in_array($sending_messenger, $with_messengers[ $message->messenger() ])
513
+			) {
514
+				throw new EE_Error(
515
+					sprintf(
516
+						esc_html__(
517
+							'The given sending messenger string (%1$s) does not match a valid sending messenger with the %2$s.  If this is incorrect, make sure that the message type has defined this messenger as a sending messenger in its $_with_messengers array.',
518
+							'event_espresso'
519
+						),
520
+						$sending_messenger,
521
+						get_class($message_type)
522
+					)
523
+				);
524
+			}
525
+		} else {
526
+			$sending_messenger = $message->messenger();
527
+		}
528
+		return EEH_MSG_Template::generate_url_trigger(
529
+			$sending_messenger,
530
+			$message->messenger(),
531
+			$message->context(),
532
+			$message->message_type(),
533
+			$registration,
534
+			$message->GRP_ID()
535
+		);
536
+	}
537
+
538
+
539
+	/**
540
+	 * This returns the url for triggering a in browser view of a specific EE_Message object.
541
+	 * @param EE_Message $message
542
+	 * @return string.
543
+	 */
544
+	public static function generate_browser_trigger(EE_Message $message)
545
+	{
546
+		$query_args = array(
547
+			'ee' => 'msg_browser_trigger',
548
+			'token' => $message->MSG_token()
549
+		);
550
+		return apply_filters(
551
+			'FHEE__EEH_MSG_Template__generate_browser_trigger',
552
+			add_query_arg($query_args, site_url()),
553
+			$message
554
+		);
555
+	}
556
+
557
+
558
+
559
+
560
+
561
+
562
+	/**
563
+	 * This returns the url for triggering an in browser view of the error saved on the incoming message object.
564
+	 * @param EE_Message $message
565
+	 * @return string
566
+	 */
567
+	public static function generate_error_display_trigger(EE_Message $message)
568
+	{
569
+		return apply_filters(
570
+			'FHEE__EEH_MSG_Template__generate_error_display_trigger',
571
+			add_query_arg(
572
+				array(
573
+					'ee' => 'msg_browser_error_trigger',
574
+					'token' => $message->MSG_token()
575
+				),
576
+				site_url()
577
+			),
578
+			$message
579
+		);
580
+	}
581
+
582
+
583
+	/**
584
+	 * This generates a url trigger for the msg_url_trigger route using the given arguments
585
+	 *
586
+	 * @param string          $sending_messenger      The sending messenger slug.
587
+	 * @param string          $generating_messenger   The generating messenger slug.
588
+	 * @param string          $context                The context for the template.
589
+	 * @param string          $message_type           The message type slug
590
+	 * @param EE_Registration $registration
591
+	 * @param integer         $message_template_group id   The EE_Message_Template_Group ID for the template.
592
+	 * @param integer         $data_id                The id to the EE_Base_Class for getting the data used by the
593
+	 *                                                trigger.
594
+	 * @return string          The generated url.
595
+	 * @throws EE_Error
596
+	 */
597
+	public static function generate_url_trigger(
598
+		$sending_messenger,
599
+		$generating_messenger,
600
+		$context,
601
+		$message_type,
602
+		EE_Registration $registration,
603
+		$message_template_group,
604
+		$data_id = 0
605
+	) {
606
+		$query_args = array(
607
+			'ee' => 'msg_url_trigger',
608
+			'snd_msgr' => $sending_messenger,
609
+			'gen_msgr' => $generating_messenger,
610
+			'message_type' => $message_type,
611
+			'context' => $context,
612
+			'token' => $registration->reg_url_link(),
613
+			'GRP_ID' => $message_template_group,
614
+			'id' => $data_id
615
+			);
616
+		$url = add_query_arg($query_args, get_home_url());
617
+
618
+		// made it here so now we can just get the url and filter it.  Filtered globally and by message type.
619
+		return apply_filters(
620
+			'FHEE__EEH_MSG_Template__generate_url_trigger',
621
+			$url,
622
+			$sending_messenger,
623
+			$generating_messenger,
624
+			$context,
625
+			$message_type,
626
+			$registration,
627
+			$message_template_group,
628
+			$data_id
629
+		);
630
+	}
631
+
632
+
633
+
634
+
635
+	/**
636
+	 * Return the specific css for the action icon given.
637
+	 *
638
+	 * @param string $type  What action to return.
639
+	 * @return string[]
640
+	 * @since 4.9.0
641
+	 */
642
+	public static function get_message_action_icon($type)
643
+	{
644
+		$action_icons = self::get_message_action_icons();
645
+		return isset($action_icons[ $type ]) ? $action_icons[ $type ] : [];
646
+	}
647
+
648
+
649
+	/**
650
+	 * This is used for retrieving the css classes used for the icons representing message actions.
651
+	 *
652
+	 * @since 4.9.0
653
+	 *
654
+	 * @return array
655
+	 */
656
+	public static function get_message_action_icons()
657
+	{
658
+		return apply_filters(
659
+			'FHEE__EEH_MSG_Template__message_action_icons',
660
+			array(
661
+				'view' => array(
662
+					'label' => esc_html__('View Message', 'event_espresso'),
663
+					'css_class' => 'dashicons dashicons-visibility',
664
+				),
665
+				'error' => array(
666
+					'label' => esc_html__('View Error Message', 'event_espresso'),
667
+					'css_class' => 'dashicons dashicons-info',
668
+				),
669
+				'see_notifications_for' => array(
670
+					'label' => esc_html__('View Related Messages', 'event_espresso'),
671
+					'css_class' => 'dashicons dashicons-megaphone',
672
+				),
673
+				'generate_now' => array(
674
+					'label' => esc_html__('Generate the message now.', 'event_espresso'),
675
+					'css_class' => 'dashicons dashicons-admin-tools',
676
+				),
677
+				'send_now' => array(
678
+					'label' => esc_html__('Send Immediately', 'event_espresso'),
679
+					'css_class' => 'dashicons dashicons-controls-forward',
680
+				),
681
+				'queue_for_resending' => array(
682
+					'label' => esc_html__('Queue for Resending', 'event_espresso'),
683
+					'css_class' => 'dashicons dashicons-controls-repeat',
684
+				),
685
+				'view_transaction' => array(
686
+					'label' => esc_html__('View related Transaction', 'event_espresso'),
687
+					'css_class' => 'dashicons dashicons-cart',
688
+				)
689
+			)
690
+		);
691
+	}
692
+
693
+
694
+	/**
695
+	 * This returns the url for a given action related to EE_Message.
696
+	 *
697
+	 * @param string     $type         What type of action to return the url for.
698
+	 * @param EE_Message $message      Required for generating the correct url for some types.
699
+	 * @param array      $query_params Any additional query params to be included with the generated url.
700
+	 *
701
+	 * @return string
702
+	 * @throws EE_Error
703
+	 * @throws ReflectionException
704
+	 * @since 4.9.0
705
+	 *
706
+	 */
707
+	public static function get_message_action_url($type, EE_Message $message = null, $query_params = array())
708
+	{
709
+		$action_urls = self::get_message_action_urls($message, $query_params);
710
+		return isset($action_urls[ $type ])  ? $action_urls[ $type ] : '';
711
+	}
712
+
713
+
714
+	/**
715
+	 * This returns all the current urls for EE_Message actions.
716
+	 *
717
+	 * @since 4.9.0
718
+	 *
719
+	 * @param EE_Message $message      The EE_Message object required to generate correct urls for some types.
720
+	 * @param array      $query_params Any additional query_params to be included with the generated url.
721
+	 *
722
+	 * @return array
723
+	 * @throws EE_Error
724
+	 * @throws ReflectionException
725
+	 */
726
+	public static function get_message_action_urls(EE_Message $message = null, $query_params = array())
727
+	{
728
+		EE_Registry::instance()->load_helper('URL');
729
+		// if $message is not an instance of EE_Message then let's just do a dummy.
730
+		$message = empty($message) ? EE_Message_Factory::create() : $message;
731
+		$action_urls =  apply_filters(
732
+			'FHEE__EEH_MSG_Template__get_message_action_url',
733
+			array(
734
+				'view' => EEH_MSG_Template::generate_browser_trigger($message),
735
+				'error' => EEH_MSG_Template::generate_error_display_trigger($message),
736
+				'see_notifications_for' => EEH_URL::add_query_args_and_nonce(
737
+					array_merge(
738
+						array(
739
+							'page' => 'espresso_messages',
740
+							'action' => 'default',
741
+							'filterby' => 1,
742
+						),
743
+						$query_params
744
+					),
745
+					admin_url('admin.php')
746
+				),
747
+				'generate_now' => EEH_URL::add_query_args_and_nonce(
748
+					array(
749
+						'page' => 'espresso_messages',
750
+						'action' => 'generate_now',
751
+						'MSG_ID' => $message->ID()
752
+					),
753
+					admin_url('admin.php')
754
+				),
755
+				'send_now' => EEH_URL::add_query_args_and_nonce(
756
+					array(
757
+						'page' => 'espresso_messages',
758
+						'action' => 'send_now',
759
+						'MSG_ID' => $message->ID()
760
+					),
761
+					admin_url('admin.php')
762
+				),
763
+				'queue_for_resending' => EEH_URL::add_query_args_and_nonce(
764
+					array(
765
+						'page' => 'espresso_messages',
766
+						'action' => 'queue_for_resending',
767
+						'MSG_ID' => $message->ID()
768
+					),
769
+					admin_url('admin.php')
770
+				),
771
+			)
772
+		);
773
+		if (
774
+			$message->TXN_ID() > 0
775
+			&& EE_Registry::instance()->CAP->current_user_can(
776
+				'ee_read_transaction',
777
+				'espresso_transactions_default',
778
+				$message->TXN_ID()
779
+			)
780
+		) {
781
+			$action_urls['view_transaction'] = EEH_URL::add_query_args_and_nonce(
782
+				array(
783
+					'page' => 'espresso_transactions',
784
+					'action' => 'view_transaction',
785
+					'TXN_ID' => $message->TXN_ID()
786
+				),
787
+				admin_url('admin.php')
788
+			);
789
+		} else {
790
+			$action_urls['view_transaction'] = '';
791
+		}
792
+		return $action_urls;
793
+	}
794
+
795
+
796
+	/**
797
+	 * This returns a generated link html including the icon used for the action link for EE_Message actions.
798
+	 *
799
+	 * @param string          $type         What type of action the link is for (if invalid type is passed in then an
800
+	 *                                      empty string is returned)
801
+	 * @param EE_Message|null $message      The EE_Message object (required for some actions to generate correctly)
802
+	 * @param array           $query_params Any extra query params to include in the generated link.
803
+	 *
804
+	 * @return string
805
+	 * @throws EE_Error
806
+	 * @throws ReflectionException
807
+	 * @since 4.9.0
808
+	 *
809
+	 */
810
+	public static function get_message_action_link($type, EE_Message $message = null, $query_params = array())
811
+	{
812
+		$url = EEH_MSG_Template::get_message_action_url($type, $message, $query_params);
813
+		$icon_css = EEH_MSG_Template::get_message_action_icon($type);
814
+		$label = $icon_css['label'] ?? null;
815
+		$label = $label ? 'aria-label="' . $label . '"' : '';
816
+		$class = $label ? ' ee-aria-tooltip' : '';
817
+
818
+		if (empty($url) || empty($icon_css) || ! isset($icon_css['css_class'])) {
819
+			return '';
820
+		}
821
+
822
+		$icon_css_class = $icon_css['css_class'] . apply_filters(
823
+			'FHEE__EEH_MSG_Template__get_message_action_link__icon_css_class',
824
+			' js-ee-message-action-link ee-message-action-link-' . $type,
825
+			$type,
826
+			$message,
827
+			$query_params
828
+		);
829
+
830
+		return '
831 831
             <a href="' . $url . '" ' . $label . ' class="button button--icon-only' . $class . '">
832 832
                 <span class="' .  esc_attr($icon_css_class) . '"></span>
833 833
             </a>';
834
-    }
835
-
836
-
837
-
838
-
839
-
840
-    /**
841
-     * This returns an array with keys as reg statuses and values as the corresponding message type slug (filtered).
842
-     *
843
-     * @since 4.9.0
844
-     * @return array
845
-     */
846
-    public static function reg_status_to_message_type_array()
847
-    {
848
-        return (array) apply_filters(
849
-            'FHEE__EEH_MSG_Template__reg_status_to_message_type_array',
850
-            array(
851
-                RegStatus::APPROVED => 'registration',
852
-                RegStatus::PENDING_PAYMENT => 'pending_approval',
853
-                RegStatus::AWAITING_REVIEW => 'not_approved_registration',
854
-                RegStatus::CANCELLED => 'cancelled_registration',
855
-                RegStatus::DECLINED => 'declined_registration'
856
-            )
857
-        );
858
-    }
859
-
860
-
861
-
862
-
863
-    /**
864
-     * This returns the corresponding registration message type slug to the given reg status. If there isn't a
865
-     * match, then returns an empty string.
866
-     *
867
-     * @since 4.9.0
868
-     * @param $reg_status
869
-     * @return string
870
-     */
871
-    public static function convert_reg_status_to_message_type($reg_status)
872
-    {
873
-        $reg_status_array = self::reg_status_to_message_type_array();
874
-        return isset($reg_status_array[ $reg_status ]) ? $reg_status_array[ $reg_status ] : '';
875
-    }
876
-
877
-
878
-    /**
879
-     * This returns an array with keys as payment stati and values as the corresponding message type slug (filtered).
880
-     *
881
-     * @since 4.9.0
882
-     * @return array
883
-     */
884
-    public static function payment_status_to_message_type_array()
885
-    {
886
-        return (array) apply_filters(
887
-            'FHEE__EEH_MSG_Template__payment_status_to_message_type_array',
888
-            array(
889
-                EEM_Payment::status_id_approved => 'payment',
890
-                EEM_Payment::status_id_pending => 'payment_pending',
891
-                EEM_Payment::status_id_cancelled => 'payment_cancelled',
892
-                EEM_Payment::status_id_declined => 'payment_declined',
893
-                EEM_Payment::status_id_failed => 'payment_failed'
894
-            )
895
-        );
896
-    }
897
-
898
-
899
-
900
-
901
-    /**
902
-     * This returns the corresponding payment message type slug to the given payment status. If there isn't a match then
903
-     * an empty string is returned
904
-     *
905
-     * @since 4.9.0
906
-     * @param $payment_status
907
-     * @return string
908
-     */
909
-    public static function convert_payment_status_to_message_type($payment_status)
910
-    {
911
-        $payment_status_array = self::payment_status_to_message_type_array();
912
-        return isset($payment_status_array[ $payment_status ]) ? $payment_status_array[ $payment_status ] : '';
913
-    }
914
-
915
-
916
-    /**
917
-     * This is used to retrieve the template pack for the given name.
918
-     *
919
-     * @param string $template_pack_name  should match the set `dbref` property value on the EE_Messages_Template_Pack.
920
-     *
921
-     * @return EE_Messages_Template_Pack
922
-     */
923
-    public static function get_template_pack($template_pack_name)
924
-    {
925
-        if (! self::$_template_pack_collection instanceof EE_Object_Collection) {
926
-            self::$_template_pack_collection = new EE_Messages_Template_Pack_Collection();
927
-        }
928
-
929
-        // first see if in collection already
930
-        $template_pack = self::$_template_pack_collection->get_by_name($template_pack_name);
931
-
932
-        if ($template_pack instanceof EE_Messages_Template_Pack) {
933
-            return $template_pack;
934
-        }
935
-
936
-        // nope...let's get it.
937
-        // not set yet so let's attempt to get it.
938
-        $pack_class_name = 'EE_Messages_Template_Pack_' . str_replace(
939
-            ' ',
940
-            '_',
941
-            ucwords(
942
-                str_replace('_', ' ', $template_pack_name)
943
-            )
944
-        );
945
-        if (! class_exists($pack_class_name) && $template_pack_name !== 'default') {
946
-            return self::get_template_pack('default');
947
-        } else {
948
-            $template_pack = new $pack_class_name();
949
-            self::$_template_pack_collection->add($template_pack);
950
-            return $template_pack;
951
-        }
952
-    }
953
-
954
-
955
-
956
-
957
-    /**
958
-     * Globs template packs installed in core and returns the template pack collection with all installed template packs
959
-     * in it.
960
-     *
961
-     * @since 4.9.0
962
-     *
963
-     * @return EE_Messages_Template_Pack_Collection
964
-     */
965
-    public static function get_template_pack_collection()
966
-    {
967
-        $new_collection = false;
968
-        if (! self::$_template_pack_collection instanceof EE_Messages_Template_Pack_Collection) {
969
-            self::$_template_pack_collection = new EE_Messages_Template_Pack_Collection();
970
-            $new_collection = true;
971
-        }
972
-
973
-        // glob the defaults directory for messages
974
-        $templates = glob(EE_LIBRARIES . 'messages/defaults/*', GLOB_ONLYDIR);
975
-        foreach ($templates as $template_path) {
976
-            // grab folder name
977
-            $template = basename($template_path);
978
-
979
-            if (! $new_collection) {
980
-                // already have it?
981
-                if (self::$_template_pack_collection->get_by_name($template) instanceof EE_Messages_Template_Pack) {
982
-                    continue;
983
-                }
984
-            }
985
-
986
-            // setup classname.
987
-            $template_pack_class_name = 'EE_Messages_Template_Pack_' . str_replace(
988
-                ' ',
989
-                '_',
990
-                ucwords(
991
-                    str_replace(
992
-                        '_',
993
-                        ' ',
994
-                        $template
995
-                    )
996
-                )
997
-            );
998
-            if (! class_exists($template_pack_class_name)) {
999
-                continue;
1000
-            }
1001
-            self::$_template_pack_collection->add(new $template_pack_class_name());
1002
-        }
1003
-
1004
-        /**
1005
-         * Filter for plugins to add in any additional template packs
1006
-         * Note the filter name here is for backward compat, this used to be found in EED_Messages.
1007
-         */
1008
-        $additional_template_packs = apply_filters('FHEE__EED_Messages__get_template_packs__template_packs', array());
1009
-        foreach ((array) $additional_template_packs as $template_pack) {
1010
-            if (
1011
-                self::$_template_pack_collection->get_by_name(
1012
-                    $template_pack->dbref
1013
-                ) instanceof EE_Messages_Template_Pack
1014
-            ) {
1015
-                continue;
1016
-            }
1017
-            self::$_template_pack_collection->add($template_pack);
1018
-        }
1019
-        return self::$_template_pack_collection;
1020
-    }
1021
-
1022
-
1023
-    /**
1024
-     * This is a wrapper for the protected _create_new_templates function
1025
-     *
1026
-     * @param string $messenger_name
1027
-     * @param string $message_type_name message type that the templates are being created for
1028
-     * @param int    $GRP_ID
1029
-     * @param bool   $global
1030
-     * @return array
1031
-     * @throws EE_Error
1032
-     * @throws ReflectionException
1033
-     */
1034
-    public static function create_new_templates($messenger_name, $message_type_name, $GRP_ID = 0, $global = false)
1035
-    {
1036
-        /** @type EE_Message_Resource_Manager $Message_Resource_Manager */
1037
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1038
-        $messenger = $Message_Resource_Manager->valid_messenger($messenger_name);
1039
-        $message_type = $Message_Resource_Manager->valid_message_type($message_type_name);
1040
-        if (! EEH_MSG_Template::message_type_has_active_templates_for_messenger($messenger, $message_type, $global)) {
1041
-            return array();
1042
-        }
1043
-        // whew made it this far!  Okay, let's go ahead and create the templates then
1044
-        return EEH_MSG_Template::_create_new_templates($messenger, $message_type, $GRP_ID, $global);
1045
-    }
1046
-
1047
-
1048
-    /**
1049
-     * @param EE_messenger     $messenger
1050
-     * @param EE_message_type  $message_type
1051
-     * @param                  $GRP_ID
1052
-     * @param                  $global
1053
-     * @return array|mixed
1054
-     * @throws EE_Error
1055
-     * @throws ReflectionException
1056
-     */
1057
-    protected static function _create_new_templates(EE_messenger $messenger, EE_message_type $message_type, $GRP_ID, $global)
1058
-    {
1059
-        // if we're creating a custom template then we don't need to use the defaults class
1060
-        if (! $global) {
1061
-            return EEH_MSG_Template::_create_custom_template_group($messenger, $message_type, $GRP_ID);
1062
-        }
1063
-        /** @type EE_Messages_Template_Defaults $Message_Template_Defaults */
1064
-        $Message_Template_Defaults = EE_Registry::factory(
1065
-            'EE_Messages_Template_Defaults',
1066
-            array( $messenger, $message_type, $GRP_ID )
1067
-        );
1068
-        // generate templates
1069
-        $success = $Message_Template_Defaults->create_new_templates();
1070
-
1071
-        // if creating the template failed.  Then we should deactivate the related message_type for the messenger because
1072
-        // its not active if it doesn't have a template.  Note this is only happening for GLOBAL template creation
1073
-        // attempts.
1074
-        if (! $success) {
1075
-            /** @var EE_Message_Resource_Manager $message_resource_manager */
1076
-            $message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1077
-            $message_resource_manager->deactivate_message_type_for_messenger($message_type->name, $messenger->name);
1078
-        }
1079
-
1080
-        /**
1081
-         * $success is in an array in the following format
1082
-         * array(
1083
-         *    'GRP_ID' => $new_grp_id,
1084
-         *    'MTP_context' => $first_context_in_new_templates,
1085
-         * )
1086
-         */
1087
-        return $success;
1088
-    }
1089
-
1090
-
1091
-    /**
1092
-     * This creates a custom template using the incoming GRP_ID
1093
-     *
1094
-     * @param EE_messenger    $messenger
1095
-     * @param EE_message_type $message_type
1096
-     * @param int             $GRP_ID           GRP_ID for the template_group being used as the base
1097
-     * @return  array $success              This will be an array in the format:
1098
-     *                                          array(
1099
-     *                                          'GRP_ID' => $new_grp_id,
1100
-     *                                          'MTP_context' => $first_context_in_created_template
1101
-     *                                          )
1102
-     * @throws EE_Error
1103
-     * @throws ReflectionException
1104
-     * @access private
1105
-     */
1106
-    private static function _create_custom_template_group(EE_messenger $messenger, EE_message_type $message_type, $GRP_ID)
1107
-    {
1108
-        // defaults
1109
-        $success = array( 'GRP_ID' => null, 'MTP_context' => '' );
1110
-        // get the template group to use as a template from the db.  If $GRP_ID is empty then we'll assume the base will be the global template matching the messenger and message type.
1111
-        $Message_Template_Group = empty($GRP_ID)
1112
-            ? EEM_Message_Template_Group::instance()->get_one(
1113
-                array(
1114
-                    array(
1115
-                        'MTP_messenger'    => $messenger->name,
1116
-                        'MTP_message_type' => $message_type->name,
1117
-                        'MTP_is_global'    => true
1118
-                    )
1119
-                )
1120
-            )
1121
-            : EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1122
-        // if we don't have a mtg at this point then we need to bail.
1123
-        if (! $Message_Template_Group instanceof EE_Message_Template_Group) {
1124
-            EE_Error::add_error(
1125
-                sprintf(
1126
-                    esc_html__(
1127
-                        'Something went wrong with generating the custom template from this group id: %s.  This usually happens when there is no matching message template group in the db.',
1128
-                        'event_espresso'
1129
-                    ),
1130
-                    $GRP_ID
1131
-                ),
1132
-                __FILE__,
1133
-                __FUNCTION__,
1134
-                __LINE__
1135
-            );
1136
-            return $success;
1137
-        }
1138
-        // let's get all the related message_template objects for this group.
1139
-        $message_templates = $Message_Template_Group->message_templates();
1140
-        // now we have what we need to setup the new template
1141
-        $new_mtg = clone $Message_Template_Group;
1142
-        $new_mtg->set('GRP_ID', 0);
1143
-        $new_mtg->set('MTP_is_global', false);
1144
-
1145
-        /** @var RequestInterface $request */
1146
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1147
-        $template_name = $request->isAjax() && $request->requestParamIsSet('templateName')
1148
-            ? $request->getRequestParam('templateName')
1149
-            : sprintf(
1150
-                esc_html__('Custom %1$s', 'event_espresso'),
1151
-                ucwords($message_type->label['singular']) ?? esc_html__('Template', 'event_espresso')
1152
-            );
1153
-        $template_description = $request->isAjax() && $request->requestParamIsSet('templateDescription')
1154
-            ? $request->getRequestParam('templateDescription')
1155
-            : sprintf(
1156
-                esc_html__(
1157
-                    'This is a custom template that was created for the %s messenger and %s message type.',
1158
-                    'event_espresso'
1159
-                ),
1160
-                $new_mtg->messenger_obj()->label['singular'],
1161
-                $new_mtg->message_type_obj()->label['singular']
1162
-            );
1163
-        $new_mtg->set('MTP_name', $template_name);
1164
-        $new_mtg->set('MTP_description', $template_description);
1165
-        // remove ALL relations on this template group so they don't get saved!
1166
-        $new_mtg->_remove_relations('Message_Template');
1167
-        $new_mtg->save();
1168
-        $success['GRP_ID'] = $new_mtg->ID();
1169
-        $success['template_name'] = $template_name;
1170
-        // add new message templates and add relation to.
1171
-        foreach ($message_templates as $message_template) {
1172
-            if (! $message_template instanceof EE_Message_Template) {
1173
-                continue;
1174
-            }
1175
-            $new_message_template = clone $message_template;
1176
-            $new_message_template->set('MTP_ID', 0);
1177
-            $new_message_template->set('GRP_ID', $new_mtg->ID()); // relation
1178
-            $new_message_template->save();
1179
-            if (empty($success['MTP_context']) && $new_message_template->get('MTP_context') !== 'admin') {
1180
-                $success['MTP_context'] = $new_message_template->get('MTP_context');
1181
-            }
1182
-        }
1183
-        return $success;
1184
-    }
1185
-
1186
-
1187
-    /**
1188
-     * message_type_has_active_templates_for_messenger
1189
-     *
1190
-     * @param EE_messenger    $messenger
1191
-     * @param EE_message_type $message_type
1192
-     * @param bool            $global
1193
-     * @return bool
1194
-     * @throws EE_Error
1195
-     */
1196
-    public static function message_type_has_active_templates_for_messenger(
1197
-        EE_messenger $messenger,
1198
-        EE_message_type $message_type,
1199
-        $global = false
1200
-    ) {
1201
-        // is given message_type valid for given messenger (if this is not a global save)
1202
-        if ($global) {
1203
-            return true;
1204
-        }
1205
-        $active_templates = EEM_Message_Template_Group::instance()->count(
1206
-            array(
1207
-                array(
1208
-                    'MTP_is_active'    => true,
1209
-                    'MTP_messenger'    => $messenger->name,
1210
-                    'MTP_message_type' => $message_type->name
1211
-                )
1212
-            )
1213
-        );
1214
-        if ($active_templates > 0) {
1215
-            return true;
1216
-        }
1217
-        EE_Error::add_error(
1218
-            sprintf(
1219
-                esc_html__(
1220
-                    'The %1$s message type is not registered with the %2$s messenger. Please visit the Messenger activation page to assign this message type first if you want to use it.',
1221
-                    'event_espresso'
1222
-                ),
1223
-                $message_type->name,
1224
-                $messenger->name
1225
-            ),
1226
-            __FILE__,
1227
-            __FUNCTION__,
1228
-            __LINE__
1229
-        );
1230
-        return false;
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     * get_fields
1236
-     * This takes a given messenger and message type and returns all the template fields indexed by context (and with field type).
1237
-     *
1238
-     * @param string $messenger_name    name of EE_messenger
1239
-     * @param string $message_type_name name of EE_message_type
1240
-     * @return array
1241
-     * @throws EE_Error
1242
-     * @throws ReflectionException
1243
-     */
1244
-    public static function get_fields($messenger_name, $message_type_name)
1245
-    {
1246
-        $template_fields = array();
1247
-        /** @type EE_Message_Resource_Manager $Message_Resource_Manager */
1248
-        $Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1249
-        $messenger = $Message_Resource_Manager->valid_messenger($messenger_name);
1250
-        $message_type = $Message_Resource_Manager->valid_message_type($message_type_name);
1251
-        if (! EEH_MSG_Template::message_type_has_active_templates_for_messenger($messenger, $message_type)) {
1252
-            return array();
1253
-        }
1254
-
1255
-        $excluded_fields_for_messenger = $message_type->excludedFieldsForMessenger($messenger_name);
1256
-
1257
-        // okay now let's assemble an array with the messenger template fields added to the message_type contexts.
1258
-        foreach ($message_type->get_contexts() as $context => $details) {
1259
-            foreach ($messenger->get_template_fields() as $field => $value) {
1260
-                if (in_array($field, $excluded_fields_for_messenger, true)) {
1261
-                    continue;
1262
-                }
1263
-                $template_fields[ $context ][ $field ] = $value;
1264
-            }
1265
-        }
1266
-        if (empty($template_fields)) {
1267
-            EE_Error::add_error(
1268
-                esc_html__('Something went wrong and we couldn\'t get any templates assembled', 'event_espresso'),
1269
-                __FILE__,
1270
-                __FUNCTION__,
1271
-                __LINE__
1272
-            );
1273
-            return array();
1274
-        }
1275
-        return $template_fields;
1276
-    }
834
+	}
835
+
836
+
837
+
838
+
839
+
840
+	/**
841
+	 * This returns an array with keys as reg statuses and values as the corresponding message type slug (filtered).
842
+	 *
843
+	 * @since 4.9.0
844
+	 * @return array
845
+	 */
846
+	public static function reg_status_to_message_type_array()
847
+	{
848
+		return (array) apply_filters(
849
+			'FHEE__EEH_MSG_Template__reg_status_to_message_type_array',
850
+			array(
851
+				RegStatus::APPROVED => 'registration',
852
+				RegStatus::PENDING_PAYMENT => 'pending_approval',
853
+				RegStatus::AWAITING_REVIEW => 'not_approved_registration',
854
+				RegStatus::CANCELLED => 'cancelled_registration',
855
+				RegStatus::DECLINED => 'declined_registration'
856
+			)
857
+		);
858
+	}
859
+
860
+
861
+
862
+
863
+	/**
864
+	 * This returns the corresponding registration message type slug to the given reg status. If there isn't a
865
+	 * match, then returns an empty string.
866
+	 *
867
+	 * @since 4.9.0
868
+	 * @param $reg_status
869
+	 * @return string
870
+	 */
871
+	public static function convert_reg_status_to_message_type($reg_status)
872
+	{
873
+		$reg_status_array = self::reg_status_to_message_type_array();
874
+		return isset($reg_status_array[ $reg_status ]) ? $reg_status_array[ $reg_status ] : '';
875
+	}
876
+
877
+
878
+	/**
879
+	 * This returns an array with keys as payment stati and values as the corresponding message type slug (filtered).
880
+	 *
881
+	 * @since 4.9.0
882
+	 * @return array
883
+	 */
884
+	public static function payment_status_to_message_type_array()
885
+	{
886
+		return (array) apply_filters(
887
+			'FHEE__EEH_MSG_Template__payment_status_to_message_type_array',
888
+			array(
889
+				EEM_Payment::status_id_approved => 'payment',
890
+				EEM_Payment::status_id_pending => 'payment_pending',
891
+				EEM_Payment::status_id_cancelled => 'payment_cancelled',
892
+				EEM_Payment::status_id_declined => 'payment_declined',
893
+				EEM_Payment::status_id_failed => 'payment_failed'
894
+			)
895
+		);
896
+	}
897
+
898
+
899
+
900
+
901
+	/**
902
+	 * This returns the corresponding payment message type slug to the given payment status. If there isn't a match then
903
+	 * an empty string is returned
904
+	 *
905
+	 * @since 4.9.0
906
+	 * @param $payment_status
907
+	 * @return string
908
+	 */
909
+	public static function convert_payment_status_to_message_type($payment_status)
910
+	{
911
+		$payment_status_array = self::payment_status_to_message_type_array();
912
+		return isset($payment_status_array[ $payment_status ]) ? $payment_status_array[ $payment_status ] : '';
913
+	}
914
+
915
+
916
+	/**
917
+	 * This is used to retrieve the template pack for the given name.
918
+	 *
919
+	 * @param string $template_pack_name  should match the set `dbref` property value on the EE_Messages_Template_Pack.
920
+	 *
921
+	 * @return EE_Messages_Template_Pack
922
+	 */
923
+	public static function get_template_pack($template_pack_name)
924
+	{
925
+		if (! self::$_template_pack_collection instanceof EE_Object_Collection) {
926
+			self::$_template_pack_collection = new EE_Messages_Template_Pack_Collection();
927
+		}
928
+
929
+		// first see if in collection already
930
+		$template_pack = self::$_template_pack_collection->get_by_name($template_pack_name);
931
+
932
+		if ($template_pack instanceof EE_Messages_Template_Pack) {
933
+			return $template_pack;
934
+		}
935
+
936
+		// nope...let's get it.
937
+		// not set yet so let's attempt to get it.
938
+		$pack_class_name = 'EE_Messages_Template_Pack_' . str_replace(
939
+			' ',
940
+			'_',
941
+			ucwords(
942
+				str_replace('_', ' ', $template_pack_name)
943
+			)
944
+		);
945
+		if (! class_exists($pack_class_name) && $template_pack_name !== 'default') {
946
+			return self::get_template_pack('default');
947
+		} else {
948
+			$template_pack = new $pack_class_name();
949
+			self::$_template_pack_collection->add($template_pack);
950
+			return $template_pack;
951
+		}
952
+	}
953
+
954
+
955
+
956
+
957
+	/**
958
+	 * Globs template packs installed in core and returns the template pack collection with all installed template packs
959
+	 * in it.
960
+	 *
961
+	 * @since 4.9.0
962
+	 *
963
+	 * @return EE_Messages_Template_Pack_Collection
964
+	 */
965
+	public static function get_template_pack_collection()
966
+	{
967
+		$new_collection = false;
968
+		if (! self::$_template_pack_collection instanceof EE_Messages_Template_Pack_Collection) {
969
+			self::$_template_pack_collection = new EE_Messages_Template_Pack_Collection();
970
+			$new_collection = true;
971
+		}
972
+
973
+		// glob the defaults directory for messages
974
+		$templates = glob(EE_LIBRARIES . 'messages/defaults/*', GLOB_ONLYDIR);
975
+		foreach ($templates as $template_path) {
976
+			// grab folder name
977
+			$template = basename($template_path);
978
+
979
+			if (! $new_collection) {
980
+				// already have it?
981
+				if (self::$_template_pack_collection->get_by_name($template) instanceof EE_Messages_Template_Pack) {
982
+					continue;
983
+				}
984
+			}
985
+
986
+			// setup classname.
987
+			$template_pack_class_name = 'EE_Messages_Template_Pack_' . str_replace(
988
+				' ',
989
+				'_',
990
+				ucwords(
991
+					str_replace(
992
+						'_',
993
+						' ',
994
+						$template
995
+					)
996
+				)
997
+			);
998
+			if (! class_exists($template_pack_class_name)) {
999
+				continue;
1000
+			}
1001
+			self::$_template_pack_collection->add(new $template_pack_class_name());
1002
+		}
1003
+
1004
+		/**
1005
+		 * Filter for plugins to add in any additional template packs
1006
+		 * Note the filter name here is for backward compat, this used to be found in EED_Messages.
1007
+		 */
1008
+		$additional_template_packs = apply_filters('FHEE__EED_Messages__get_template_packs__template_packs', array());
1009
+		foreach ((array) $additional_template_packs as $template_pack) {
1010
+			if (
1011
+				self::$_template_pack_collection->get_by_name(
1012
+					$template_pack->dbref
1013
+				) instanceof EE_Messages_Template_Pack
1014
+			) {
1015
+				continue;
1016
+			}
1017
+			self::$_template_pack_collection->add($template_pack);
1018
+		}
1019
+		return self::$_template_pack_collection;
1020
+	}
1021
+
1022
+
1023
+	/**
1024
+	 * This is a wrapper for the protected _create_new_templates function
1025
+	 *
1026
+	 * @param string $messenger_name
1027
+	 * @param string $message_type_name message type that the templates are being created for
1028
+	 * @param int    $GRP_ID
1029
+	 * @param bool   $global
1030
+	 * @return array
1031
+	 * @throws EE_Error
1032
+	 * @throws ReflectionException
1033
+	 */
1034
+	public static function create_new_templates($messenger_name, $message_type_name, $GRP_ID = 0, $global = false)
1035
+	{
1036
+		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
1037
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1038
+		$messenger = $Message_Resource_Manager->valid_messenger($messenger_name);
1039
+		$message_type = $Message_Resource_Manager->valid_message_type($message_type_name);
1040
+		if (! EEH_MSG_Template::message_type_has_active_templates_for_messenger($messenger, $message_type, $global)) {
1041
+			return array();
1042
+		}
1043
+		// whew made it this far!  Okay, let's go ahead and create the templates then
1044
+		return EEH_MSG_Template::_create_new_templates($messenger, $message_type, $GRP_ID, $global);
1045
+	}
1046
+
1047
+
1048
+	/**
1049
+	 * @param EE_messenger     $messenger
1050
+	 * @param EE_message_type  $message_type
1051
+	 * @param                  $GRP_ID
1052
+	 * @param                  $global
1053
+	 * @return array|mixed
1054
+	 * @throws EE_Error
1055
+	 * @throws ReflectionException
1056
+	 */
1057
+	protected static function _create_new_templates(EE_messenger $messenger, EE_message_type $message_type, $GRP_ID, $global)
1058
+	{
1059
+		// if we're creating a custom template then we don't need to use the defaults class
1060
+		if (! $global) {
1061
+			return EEH_MSG_Template::_create_custom_template_group($messenger, $message_type, $GRP_ID);
1062
+		}
1063
+		/** @type EE_Messages_Template_Defaults $Message_Template_Defaults */
1064
+		$Message_Template_Defaults = EE_Registry::factory(
1065
+			'EE_Messages_Template_Defaults',
1066
+			array( $messenger, $message_type, $GRP_ID )
1067
+		);
1068
+		// generate templates
1069
+		$success = $Message_Template_Defaults->create_new_templates();
1070
+
1071
+		// if creating the template failed.  Then we should deactivate the related message_type for the messenger because
1072
+		// its not active if it doesn't have a template.  Note this is only happening for GLOBAL template creation
1073
+		// attempts.
1074
+		if (! $success) {
1075
+			/** @var EE_Message_Resource_Manager $message_resource_manager */
1076
+			$message_resource_manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1077
+			$message_resource_manager->deactivate_message_type_for_messenger($message_type->name, $messenger->name);
1078
+		}
1079
+
1080
+		/**
1081
+		 * $success is in an array in the following format
1082
+		 * array(
1083
+		 *    'GRP_ID' => $new_grp_id,
1084
+		 *    'MTP_context' => $first_context_in_new_templates,
1085
+		 * )
1086
+		 */
1087
+		return $success;
1088
+	}
1089
+
1090
+
1091
+	/**
1092
+	 * This creates a custom template using the incoming GRP_ID
1093
+	 *
1094
+	 * @param EE_messenger    $messenger
1095
+	 * @param EE_message_type $message_type
1096
+	 * @param int             $GRP_ID           GRP_ID for the template_group being used as the base
1097
+	 * @return  array $success              This will be an array in the format:
1098
+	 *                                          array(
1099
+	 *                                          'GRP_ID' => $new_grp_id,
1100
+	 *                                          'MTP_context' => $first_context_in_created_template
1101
+	 *                                          )
1102
+	 * @throws EE_Error
1103
+	 * @throws ReflectionException
1104
+	 * @access private
1105
+	 */
1106
+	private static function _create_custom_template_group(EE_messenger $messenger, EE_message_type $message_type, $GRP_ID)
1107
+	{
1108
+		// defaults
1109
+		$success = array( 'GRP_ID' => null, 'MTP_context' => '' );
1110
+		// get the template group to use as a template from the db.  If $GRP_ID is empty then we'll assume the base will be the global template matching the messenger and message type.
1111
+		$Message_Template_Group = empty($GRP_ID)
1112
+			? EEM_Message_Template_Group::instance()->get_one(
1113
+				array(
1114
+					array(
1115
+						'MTP_messenger'    => $messenger->name,
1116
+						'MTP_message_type' => $message_type->name,
1117
+						'MTP_is_global'    => true
1118
+					)
1119
+				)
1120
+			)
1121
+			: EEM_Message_Template_Group::instance()->get_one_by_ID($GRP_ID);
1122
+		// if we don't have a mtg at this point then we need to bail.
1123
+		if (! $Message_Template_Group instanceof EE_Message_Template_Group) {
1124
+			EE_Error::add_error(
1125
+				sprintf(
1126
+					esc_html__(
1127
+						'Something went wrong with generating the custom template from this group id: %s.  This usually happens when there is no matching message template group in the db.',
1128
+						'event_espresso'
1129
+					),
1130
+					$GRP_ID
1131
+				),
1132
+				__FILE__,
1133
+				__FUNCTION__,
1134
+				__LINE__
1135
+			);
1136
+			return $success;
1137
+		}
1138
+		// let's get all the related message_template objects for this group.
1139
+		$message_templates = $Message_Template_Group->message_templates();
1140
+		// now we have what we need to setup the new template
1141
+		$new_mtg = clone $Message_Template_Group;
1142
+		$new_mtg->set('GRP_ID', 0);
1143
+		$new_mtg->set('MTP_is_global', false);
1144
+
1145
+		/** @var RequestInterface $request */
1146
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
1147
+		$template_name = $request->isAjax() && $request->requestParamIsSet('templateName')
1148
+			? $request->getRequestParam('templateName')
1149
+			: sprintf(
1150
+				esc_html__('Custom %1$s', 'event_espresso'),
1151
+				ucwords($message_type->label['singular']) ?? esc_html__('Template', 'event_espresso')
1152
+			);
1153
+		$template_description = $request->isAjax() && $request->requestParamIsSet('templateDescription')
1154
+			? $request->getRequestParam('templateDescription')
1155
+			: sprintf(
1156
+				esc_html__(
1157
+					'This is a custom template that was created for the %s messenger and %s message type.',
1158
+					'event_espresso'
1159
+				),
1160
+				$new_mtg->messenger_obj()->label['singular'],
1161
+				$new_mtg->message_type_obj()->label['singular']
1162
+			);
1163
+		$new_mtg->set('MTP_name', $template_name);
1164
+		$new_mtg->set('MTP_description', $template_description);
1165
+		// remove ALL relations on this template group so they don't get saved!
1166
+		$new_mtg->_remove_relations('Message_Template');
1167
+		$new_mtg->save();
1168
+		$success['GRP_ID'] = $new_mtg->ID();
1169
+		$success['template_name'] = $template_name;
1170
+		// add new message templates and add relation to.
1171
+		foreach ($message_templates as $message_template) {
1172
+			if (! $message_template instanceof EE_Message_Template) {
1173
+				continue;
1174
+			}
1175
+			$new_message_template = clone $message_template;
1176
+			$new_message_template->set('MTP_ID', 0);
1177
+			$new_message_template->set('GRP_ID', $new_mtg->ID()); // relation
1178
+			$new_message_template->save();
1179
+			if (empty($success['MTP_context']) && $new_message_template->get('MTP_context') !== 'admin') {
1180
+				$success['MTP_context'] = $new_message_template->get('MTP_context');
1181
+			}
1182
+		}
1183
+		return $success;
1184
+	}
1185
+
1186
+
1187
+	/**
1188
+	 * message_type_has_active_templates_for_messenger
1189
+	 *
1190
+	 * @param EE_messenger    $messenger
1191
+	 * @param EE_message_type $message_type
1192
+	 * @param bool            $global
1193
+	 * @return bool
1194
+	 * @throws EE_Error
1195
+	 */
1196
+	public static function message_type_has_active_templates_for_messenger(
1197
+		EE_messenger $messenger,
1198
+		EE_message_type $message_type,
1199
+		$global = false
1200
+	) {
1201
+		// is given message_type valid for given messenger (if this is not a global save)
1202
+		if ($global) {
1203
+			return true;
1204
+		}
1205
+		$active_templates = EEM_Message_Template_Group::instance()->count(
1206
+			array(
1207
+				array(
1208
+					'MTP_is_active'    => true,
1209
+					'MTP_messenger'    => $messenger->name,
1210
+					'MTP_message_type' => $message_type->name
1211
+				)
1212
+			)
1213
+		);
1214
+		if ($active_templates > 0) {
1215
+			return true;
1216
+		}
1217
+		EE_Error::add_error(
1218
+			sprintf(
1219
+				esc_html__(
1220
+					'The %1$s message type is not registered with the %2$s messenger. Please visit the Messenger activation page to assign this message type first if you want to use it.',
1221
+					'event_espresso'
1222
+				),
1223
+				$message_type->name,
1224
+				$messenger->name
1225
+			),
1226
+			__FILE__,
1227
+			__FUNCTION__,
1228
+			__LINE__
1229
+		);
1230
+		return false;
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 * get_fields
1236
+	 * This takes a given messenger and message type and returns all the template fields indexed by context (and with field type).
1237
+	 *
1238
+	 * @param string $messenger_name    name of EE_messenger
1239
+	 * @param string $message_type_name name of EE_message_type
1240
+	 * @return array
1241
+	 * @throws EE_Error
1242
+	 * @throws ReflectionException
1243
+	 */
1244
+	public static function get_fields($messenger_name, $message_type_name)
1245
+	{
1246
+		$template_fields = array();
1247
+		/** @type EE_Message_Resource_Manager $Message_Resource_Manager */
1248
+		$Message_Resource_Manager = EE_Registry::instance()->load_lib('Message_Resource_Manager');
1249
+		$messenger = $Message_Resource_Manager->valid_messenger($messenger_name);
1250
+		$message_type = $Message_Resource_Manager->valid_message_type($message_type_name);
1251
+		if (! EEH_MSG_Template::message_type_has_active_templates_for_messenger($messenger, $message_type)) {
1252
+			return array();
1253
+		}
1254
+
1255
+		$excluded_fields_for_messenger = $message_type->excludedFieldsForMessenger($messenger_name);
1256
+
1257
+		// okay now let's assemble an array with the messenger template fields added to the message_type contexts.
1258
+		foreach ($message_type->get_contexts() as $context => $details) {
1259
+			foreach ($messenger->get_template_fields() as $field => $value) {
1260
+				if (in_array($field, $excluded_fields_for_messenger, true)) {
1261
+					continue;
1262
+				}
1263
+				$template_fields[ $context ][ $field ] = $value;
1264
+			}
1265
+		}
1266
+		if (empty($template_fields)) {
1267
+			EE_Error::add_error(
1268
+				esc_html__('Something went wrong and we couldn\'t get any templates assembled', 'event_espresso'),
1269
+				__FILE__,
1270
+				__FUNCTION__,
1271
+				__LINE__
1272
+			);
1273
+			return array();
1274
+		}
1275
+		return $template_fields;
1276
+	}
1277 1277
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Debug_Tools.helper.php 2 patches
Indentation   +721 added lines, -721 removed lines patch added patch discarded remove patch
@@ -14,722 +14,722 @@  discard block
 block discarded – undo
14 14
  */
15 15
 class EEH_Debug_Tools
16 16
 {
17
-    /**
18
-     *    instance of the EEH_Autoloader object
19
-     *
20
-     * @var    $_instance
21
-     * @access    private
22
-     */
23
-    private static $_instance;
24
-
25
-    /**
26
-     * @var array
27
-     */
28
-    protected $_memory_usage_points = array();
29
-
30
-
31
-
32
-    /**
33
-     * @singleton method used to instantiate class object
34
-     * @access    public
35
-     * @return EEH_Debug_Tools
36
-     */
37
-    public static function instance()
38
-    {
39
-        // check if class object is instantiated, and instantiated properly
40
-        if (! self::$_instance instanceof EEH_Debug_Tools) {
41
-            self::$_instance = new self();
42
-        }
43
-        return self::$_instance;
44
-    }
45
-
46
-
47
-
48
-    /**
49
-     * private class constructor
50
-     */
51
-    private function __construct()
52
-    {
53
-        // load Kint PHP debugging library
54
-        if (
55
-            defined('EE_LOAD_KINT')
56
-            && ! class_exists('Kint')
57
-            && file_exists(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php')
58
-        ) {
59
-            // despite EE4 having a check for an existing copy of the Kint debugging class,
60
-            // if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
61
-            // then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
62
-            // so we've moved it to our test folder so that it is not included with production releases
63
-            // plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
64
-            require_once(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php');
65
-        }
66
-        $plugin = basename(EE_PLUGIN_DIR_PATH);
67
-        add_action("activate_{$plugin}", array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
68
-        add_action('activated_plugin', array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
69
-        add_action('shutdown', array('EEH_Debug_Tools', 'show_db_name'));
70
-    }
71
-
72
-
73
-
74
-    /**
75
-     *    show_db_name
76
-     *
77
-     * @return void
78
-     */
79
-    public static function show_db_name()
80
-    {
81
-        if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
82
-            echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
83
-                 . DB_NAME
84
-                 . '</p>';
85
-        }
86
-        if (EE_DEBUG) {
87
-            Benchmark::displayResults();
88
-        }
89
-    }
90
-
91
-
92
-
93
-    /**
94
-     *    dump EE_Session object at bottom of page after everything else has happened
95
-     *
96
-     * @return void
97
-     */
98
-    public function espresso_session_footer_dump()
99
-    {
100
-        if (
101
-            (defined('WP_DEBUG') && WP_DEBUG)
102
-            && ! defined('DOING_AJAX')
103
-            && class_exists('Kint')
104
-            && function_exists('wp_get_current_user')
105
-            && current_user_can('update_core')
106
-            && class_exists('EE_Registry')
107
-        ) {
108
-            Kint::dump(EE_Registry::instance()->SSN->id());
109
-            Kint::dump(EE_Registry::instance()->SSN);
110
-            //          Kint::dump( EE_Registry::instance()->SSN->get_session_data('cart')->get_tickets() );
111
-            $this->espresso_list_hooked_functions();
112
-            Benchmark::displayResults();
113
-        }
114
-    }
115
-
116
-
117
-
118
-    /**
119
-     *    List All Hooked Functions
120
-     *    to list all functions for a specific hook, add ee_list_hooks={hook-name} to URL
121
-     *    http://wp.smashingmagazine.com/2009/08/18/10-useful-wordpress-hook-hacks/
122
-     *
123
-     * @param string $tag
124
-     * @return void
125
-     */
126
-    public function espresso_list_hooked_functions($tag = '')
127
-    {
128
-        global $wp_filter;
129
-        echo '<br/><br/><br/><h3>Hooked Functions</h3>';
130
-        if ($tag) {
131
-            $hook[ $tag ] = $wp_filter[ $tag ];
132
-            if (! is_array($hook[ $tag ])) {
133
-                trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
134
-                return;
135
-            }
136
-            echo '<h5>For Tag: ' . esc_html($tag) . '</h5>';
137
-        } else {
138
-            $hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
139
-            ksort($hook);
140
-        }
141
-        foreach ($hook as $tag_name => $priorities) {
142
-            echo "<br />&gt;&gt;&gt;&gt;&gt;\t<strong>esc_html($tag_name)</strong><br />";
143
-            ksort($priorities);
144
-            foreach ($priorities as $priority => $function) {
145
-                echo esc_html($priority);
146
-                foreach ($function as $name => $properties) {
147
-                    $name = esc_html($name);
148
-                    echo "\t$name<br />";
149
-                }
150
-            }
151
-        }
152
-    }
153
-
154
-
155
-
156
-    /**
157
-     *    registered_filter_callbacks
158
-     *
159
-     * @param string $hook_name
160
-     * @return array
161
-     */
162
-    public static function registered_filter_callbacks($hook_name = '')
163
-    {
164
-        $filters = array();
165
-        global $wp_filter;
166
-        if (isset($wp_filter[ $hook_name ])) {
167
-            $filters[ $hook_name ] = array();
168
-            foreach ($wp_filter[ $hook_name ] as $priority => $callbacks) {
169
-                $filters[ $hook_name ][ $priority ] = array();
170
-                foreach ($callbacks as $callback) {
171
-                    $filters[ $hook_name ][ $priority ][] = $callback['function'];
172
-                }
173
-            }
174
-        }
175
-        return $filters;
176
-    }
177
-
178
-
179
-
180
-    /**
181
-     *    captures plugin activation errors for debugging
182
-     *
183
-     * @return void
184
-     * @throws EE_Error
185
-     */
186
-    public static function ee_plugin_activation_errors()
187
-    {
188
-        if (defined('WP_DEBUG') && WP_DEBUG) {
189
-            $activation_errors = ob_get_contents();
190
-            if (empty($activation_errors)) {
191
-                return;
192
-            }
193
-            $activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
194
-            espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
195
-            if (class_exists('EEH_File')) {
196
-                try {
197
-                    EEH_File::ensure_file_exists_and_is_writable(
198
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html'
199
-                    );
200
-                    EEH_File::write_to_file(
201
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
202
-                        $activation_errors
203
-                    );
204
-                } catch (EE_Error $e) {
205
-                    EE_Error::add_error(
206
-                        sprintf(
207
-                            esc_html__(
208
-                                'The Event Espresso activation errors file could not be setup because: %s',
209
-                                'event_espresso'
210
-                            ),
211
-                            $e->getMessage()
212
-                        ),
213
-                        __FILE__,
214
-                        __FUNCTION__,
215
-                        __LINE__
216
-                    );
217
-                }
218
-            } else {
219
-                // old school attempt
220
-                file_put_contents(
221
-                    EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
222
-                    $activation_errors
223
-                );
224
-            }
225
-            $activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
226
-            update_option('ee_plugin_activation_errors', $activation_errors);
227
-        }
228
-    }
229
-
230
-
231
-
232
-    /**
233
-     * This basically mimics the WordPress _doing_it_wrong() function except adds our own messaging etc.
234
-     * Very useful for providing helpful messages to developers when the method of doing something has been deprecated,
235
-     * or we want to make sure they use something the right way.
236
-     *
237
-     * @access public
238
-     * @param string $function      The function that was called
239
-     * @param string $message       A message explaining what has been done incorrectly
240
-     * @param string $version       The version of Event Espresso where the error was added
241
-     * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
242
-     *                              for a deprecated function. This allows deprecation to occur during one version,
243
-     *                              but not have any notices appear until a later version. This allows developers
244
-     *                              extra time to update their code before notices appear.
245
-     * @param int    $error_type
246
-     * @uses   trigger_error()
247
-     */
248
-    public function doing_it_wrong(
249
-        $function,
250
-        $message,
251
-        $version,
252
-        $applies_when = '',
253
-        $error_type = null
254
-    ) {
255
-        $applies_when = ! empty($applies_when) ? $applies_when : espresso_version();
256
-        $error_type = $error_type !== null ? $error_type : E_USER_NOTICE;
257
-        // because we swapped the parameter order around for the last two params,
258
-        // let's verify that some third party isn't still passing an error type value for the third param
259
-        if (is_int($applies_when)) {
260
-            $error_type = $applies_when;
261
-            $applies_when = espresso_version();
262
-        }
263
-        // if not displaying notices yet, then just leave
264
-        if (version_compare(espresso_version(), $applies_when, '<')) {
265
-            return;
266
-        }
267
-        do_action('AHEE__EEH_Debug_Tools__doing_it_wrong_run', $function, $message, $version);
268
-        $version = $version === null
269
-            ? ''
270
-            : sprintf(
271
-                esc_html__('(This message was added in version %s of Event Espresso)', 'event_espresso'),
272
-                $version
273
-            );
274
-        $error_message = sprintf(
275
-            esc_html__('%1$s was called %2$sincorrectly%3$s. %4$s %5$s', 'event_espresso'),
276
-            $function,
277
-            '<strong>',
278
-            '</strong>',
279
-            $message,
280
-            $version
281
-        );
282
-        // don't trigger error if doing ajax,
283
-        // instead we'll add a transient EE_Error notice that in theory should show on the next request.
284
-        if (defined('DOING_AJAX') && DOING_AJAX) {
285
-            $error_message .= ' ' . esc_html__(
286
-                'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
287
-                'event_espresso'
288
-            );
289
-            $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
290
-            $error_message .= '<ul><li>';
291
-            $error_message .= implode('</li><li>', $request->requestParams());
292
-            $error_message .= '</ul>';
293
-            EE_Error::add_error($error_message, 'debug::doing_it_wrong', $function, '42');
294
-            // now we set this on the transient so it shows up on the next request.
295
-            EE_Error::get_notices(false, true);
296
-        } else {
297
-            trigger_error($error_message, $error_type);
298
-        }
299
-    }
300
-
301
-
302
-
303
-
304
-    /**
305
-     * Logger helpers
306
-     */
307
-    /**
308
-     * debug
309
-     *
310
-     * @param string $class
311
-     * @param string $func
312
-     * @param string $line
313
-     * @param array  $info
314
-     * @param bool   $display_request
315
-     * @param string $debug_index
316
-     * @param string $debug_key
317
-     */
318
-    public static function log(
319
-        $class = '',
320
-        $func = '',
321
-        $line = '',
322
-        $info = array(),
323
-        $display_request = false,
324
-        $debug_index = '',
325
-        $debug_key = 'EE_DEBUG_SPCO'
326
-    ) {
327
-        if (defined('WP_DEBUG') && WP_DEBUG) {
328
-            $debug_key = $debug_key . '_' . EE_Session::instance()->id();
329
-            $debug_data = get_option($debug_key, array());
330
-            $default_data = array(
331
-                $class => $func . '() : ' . $line,
332
-            );
333
-            // don't serialize objects
334
-            $info = self::strip_objects($info);
335
-            $index = ! empty($debug_index) ? $debug_index : 0;
336
-            if (! isset($debug_data[ $index ])) {
337
-                $debug_data[ $index ] = array();
338
-            }
339
-            $debug_data[ $index ][ microtime() ] = array_merge($default_data, $info);
340
-            update_option($debug_key, $debug_data);
341
-        }
342
-    }
343
-
344
-
345
-
346
-    /**
347
-     * strip_objects
348
-     *
349
-     * @param array $info
350
-     * @return array
351
-     */
352
-    public static function strip_objects($info = array())
353
-    {
354
-        foreach ($info as $key => $value) {
355
-            if (is_array($value)) {
356
-                $info[ $key ] = self::strip_objects($value);
357
-            } elseif (is_object($value)) {
358
-                $object_class = get_class($value);
359
-                $info[ $object_class ] = array();
360
-                $info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
361
-                if (method_exists($value, 'ID')) {
362
-                    $info[ $object_class ]['ID'] = $value->ID();
363
-                }
364
-                if (method_exists($value, 'status')) {
365
-                    $info[ $object_class ]['status'] = $value->status();
366
-                } elseif (method_exists($value, 'status_ID')) {
367
-                    $info[ $object_class ]['status'] = $value->status_ID();
368
-                }
369
-                unset($info[ $key ]);
370
-            }
371
-        }
372
-        return (array) $info;
373
-    }
374
-
375
-
376
-
377
-    /**
378
-     * @param mixed      $var
379
-     * @param string     $var_name
380
-     * @param string     $file
381
-     * @param int|string $line
382
-     * @param int|string $heading_tag
383
-     * @param bool       $die
384
-     * @param string     $margin
385
-     */
386
-    public static function printv(
387
-        $var,
388
-        $var_name = '',
389
-        $file = '',
390
-        $line = '',
391
-        $heading_tag = 5,
392
-        $die = false,
393
-        $margin = ''
394
-    ) {
395
-        $var_name = ! $var_name ? 'string' : $var_name;
396
-        $var_name = ucwords(str_replace('$', '', $var_name));
397
-        $is_method = method_exists($var_name, $var);
398
-        $var_name = ucwords(str_replace('_', ' ', $var_name));
399
-        $heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
400
-        // $result = EEH_Debug_Tools::headingSpacer($heading_tag);
401
-        $result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
402
-        $result .= $is_method
403
-            ? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
404
-            : EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
405
-        $result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
406
-        $result .= EEH_Debug_Tools::headingX($heading_tag);
407
-        if ($die) {
408
-            die($result);
409
-        }
410
-        echo defined('WP_DEBUG') && WP_DEBUG ? $result : '';
411
-    }
412
-
413
-
414
-    protected static function headingTag($heading_tag)
415
-    {
416
-        $heading_tag = absint($heading_tag);
417
-        return $heading_tag > 0 && $heading_tag < 7 ? "h{$heading_tag}" : 'h5';
418
-    }
419
-
420
-    protected static function headingSpacer($heading_tag)
421
-    {
422
-        return EEH_Debug_Tools::plainOutput() && ($heading_tag === 'h1' || $heading_tag === 'h2')
423
-            ? self::lineBreak()
424
-            : '';
425
-    }
426
-
427
-
428
-    protected static function plainOutput()
429
-    {
430
-        return defined('EE_TESTS_DIR')
431
-               || (defined('DOING_AJAX') && DOING_AJAX && ! isset($_REQUEST['pretty_output']))
432
-               || (
433
-                   isset($_SERVER['REQUEST_URI'])
434
-                   && strpos(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), 'wp-json') !== false
435
-               );
436
-    }
437
-
438
-
439
-    /**
440
-     * @param string $var_name
441
-     * @param string $heading_tag
442
-     * @param string $margin
443
-     * @param int    $line
444
-     * @return string
445
-     */
446
-    protected static function heading($var_name = '', $heading_tag = 'h5', $margin = '', $line = 0)
447
-    {
448
-        if (EEH_Debug_Tools::plainOutput()) {
449
-            switch ($heading_tag) {
450
-                case 'h1':
451
-                    $line_breaks = EEH_Debug_Tools::lineBreak(3);
452
-                    break;
453
-                case 'h2':
454
-                    $line_breaks = EEH_Debug_Tools::lineBreak(2);
455
-                    break;
456
-                default:
457
-                    $line_breaks = EEH_Debug_Tools::lineBreak();
458
-                    break;
459
-            }
460
-            return "{$line_breaks}{$line}) {$var_name}";
461
-        }
462
-        $margin = "1rem 1rem .5rem {$margin}";
463
-        return '
17
+	/**
18
+	 *    instance of the EEH_Autoloader object
19
+	 *
20
+	 * @var    $_instance
21
+	 * @access    private
22
+	 */
23
+	private static $_instance;
24
+
25
+	/**
26
+	 * @var array
27
+	 */
28
+	protected $_memory_usage_points = array();
29
+
30
+
31
+
32
+	/**
33
+	 * @singleton method used to instantiate class object
34
+	 * @access    public
35
+	 * @return EEH_Debug_Tools
36
+	 */
37
+	public static function instance()
38
+	{
39
+		// check if class object is instantiated, and instantiated properly
40
+		if (! self::$_instance instanceof EEH_Debug_Tools) {
41
+			self::$_instance = new self();
42
+		}
43
+		return self::$_instance;
44
+	}
45
+
46
+
47
+
48
+	/**
49
+	 * private class constructor
50
+	 */
51
+	private function __construct()
52
+	{
53
+		// load Kint PHP debugging library
54
+		if (
55
+			defined('EE_LOAD_KINT')
56
+			&& ! class_exists('Kint')
57
+			&& file_exists(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php')
58
+		) {
59
+			// despite EE4 having a check for an existing copy of the Kint debugging class,
60
+			// if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
61
+			// then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
62
+			// so we've moved it to our test folder so that it is not included with production releases
63
+			// plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
64
+			require_once(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php');
65
+		}
66
+		$plugin = basename(EE_PLUGIN_DIR_PATH);
67
+		add_action("activate_{$plugin}", array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
68
+		add_action('activated_plugin', array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
69
+		add_action('shutdown', array('EEH_Debug_Tools', 'show_db_name'));
70
+	}
71
+
72
+
73
+
74
+	/**
75
+	 *    show_db_name
76
+	 *
77
+	 * @return void
78
+	 */
79
+	public static function show_db_name()
80
+	{
81
+		if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
82
+			echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
83
+				 . DB_NAME
84
+				 . '</p>';
85
+		}
86
+		if (EE_DEBUG) {
87
+			Benchmark::displayResults();
88
+		}
89
+	}
90
+
91
+
92
+
93
+	/**
94
+	 *    dump EE_Session object at bottom of page after everything else has happened
95
+	 *
96
+	 * @return void
97
+	 */
98
+	public function espresso_session_footer_dump()
99
+	{
100
+		if (
101
+			(defined('WP_DEBUG') && WP_DEBUG)
102
+			&& ! defined('DOING_AJAX')
103
+			&& class_exists('Kint')
104
+			&& function_exists('wp_get_current_user')
105
+			&& current_user_can('update_core')
106
+			&& class_exists('EE_Registry')
107
+		) {
108
+			Kint::dump(EE_Registry::instance()->SSN->id());
109
+			Kint::dump(EE_Registry::instance()->SSN);
110
+			//          Kint::dump( EE_Registry::instance()->SSN->get_session_data('cart')->get_tickets() );
111
+			$this->espresso_list_hooked_functions();
112
+			Benchmark::displayResults();
113
+		}
114
+	}
115
+
116
+
117
+
118
+	/**
119
+	 *    List All Hooked Functions
120
+	 *    to list all functions for a specific hook, add ee_list_hooks={hook-name} to URL
121
+	 *    http://wp.smashingmagazine.com/2009/08/18/10-useful-wordpress-hook-hacks/
122
+	 *
123
+	 * @param string $tag
124
+	 * @return void
125
+	 */
126
+	public function espresso_list_hooked_functions($tag = '')
127
+	{
128
+		global $wp_filter;
129
+		echo '<br/><br/><br/><h3>Hooked Functions</h3>';
130
+		if ($tag) {
131
+			$hook[ $tag ] = $wp_filter[ $tag ];
132
+			if (! is_array($hook[ $tag ])) {
133
+				trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
134
+				return;
135
+			}
136
+			echo '<h5>For Tag: ' . esc_html($tag) . '</h5>';
137
+		} else {
138
+			$hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
139
+			ksort($hook);
140
+		}
141
+		foreach ($hook as $tag_name => $priorities) {
142
+			echo "<br />&gt;&gt;&gt;&gt;&gt;\t<strong>esc_html($tag_name)</strong><br />";
143
+			ksort($priorities);
144
+			foreach ($priorities as $priority => $function) {
145
+				echo esc_html($priority);
146
+				foreach ($function as $name => $properties) {
147
+					$name = esc_html($name);
148
+					echo "\t$name<br />";
149
+				}
150
+			}
151
+		}
152
+	}
153
+
154
+
155
+
156
+	/**
157
+	 *    registered_filter_callbacks
158
+	 *
159
+	 * @param string $hook_name
160
+	 * @return array
161
+	 */
162
+	public static function registered_filter_callbacks($hook_name = '')
163
+	{
164
+		$filters = array();
165
+		global $wp_filter;
166
+		if (isset($wp_filter[ $hook_name ])) {
167
+			$filters[ $hook_name ] = array();
168
+			foreach ($wp_filter[ $hook_name ] as $priority => $callbacks) {
169
+				$filters[ $hook_name ][ $priority ] = array();
170
+				foreach ($callbacks as $callback) {
171
+					$filters[ $hook_name ][ $priority ][] = $callback['function'];
172
+				}
173
+			}
174
+		}
175
+		return $filters;
176
+	}
177
+
178
+
179
+
180
+	/**
181
+	 *    captures plugin activation errors for debugging
182
+	 *
183
+	 * @return void
184
+	 * @throws EE_Error
185
+	 */
186
+	public static function ee_plugin_activation_errors()
187
+	{
188
+		if (defined('WP_DEBUG') && WP_DEBUG) {
189
+			$activation_errors = ob_get_contents();
190
+			if (empty($activation_errors)) {
191
+				return;
192
+			}
193
+			$activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
194
+			espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
195
+			if (class_exists('EEH_File')) {
196
+				try {
197
+					EEH_File::ensure_file_exists_and_is_writable(
198
+						EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html'
199
+					);
200
+					EEH_File::write_to_file(
201
+						EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
202
+						$activation_errors
203
+					);
204
+				} catch (EE_Error $e) {
205
+					EE_Error::add_error(
206
+						sprintf(
207
+							esc_html__(
208
+								'The Event Espresso activation errors file could not be setup because: %s',
209
+								'event_espresso'
210
+							),
211
+							$e->getMessage()
212
+						),
213
+						__FILE__,
214
+						__FUNCTION__,
215
+						__LINE__
216
+					);
217
+				}
218
+			} else {
219
+				// old school attempt
220
+				file_put_contents(
221
+					EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
222
+					$activation_errors
223
+				);
224
+			}
225
+			$activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
226
+			update_option('ee_plugin_activation_errors', $activation_errors);
227
+		}
228
+	}
229
+
230
+
231
+
232
+	/**
233
+	 * This basically mimics the WordPress _doing_it_wrong() function except adds our own messaging etc.
234
+	 * Very useful for providing helpful messages to developers when the method of doing something has been deprecated,
235
+	 * or we want to make sure they use something the right way.
236
+	 *
237
+	 * @access public
238
+	 * @param string $function      The function that was called
239
+	 * @param string $message       A message explaining what has been done incorrectly
240
+	 * @param string $version       The version of Event Espresso where the error was added
241
+	 * @param string $applies_when  a version string for when you want the doing_it_wrong notice to begin appearing
242
+	 *                              for a deprecated function. This allows deprecation to occur during one version,
243
+	 *                              but not have any notices appear until a later version. This allows developers
244
+	 *                              extra time to update their code before notices appear.
245
+	 * @param int    $error_type
246
+	 * @uses   trigger_error()
247
+	 */
248
+	public function doing_it_wrong(
249
+		$function,
250
+		$message,
251
+		$version,
252
+		$applies_when = '',
253
+		$error_type = null
254
+	) {
255
+		$applies_when = ! empty($applies_when) ? $applies_when : espresso_version();
256
+		$error_type = $error_type !== null ? $error_type : E_USER_NOTICE;
257
+		// because we swapped the parameter order around for the last two params,
258
+		// let's verify that some third party isn't still passing an error type value for the third param
259
+		if (is_int($applies_when)) {
260
+			$error_type = $applies_when;
261
+			$applies_when = espresso_version();
262
+		}
263
+		// if not displaying notices yet, then just leave
264
+		if (version_compare(espresso_version(), $applies_when, '<')) {
265
+			return;
266
+		}
267
+		do_action('AHEE__EEH_Debug_Tools__doing_it_wrong_run', $function, $message, $version);
268
+		$version = $version === null
269
+			? ''
270
+			: sprintf(
271
+				esc_html__('(This message was added in version %s of Event Espresso)', 'event_espresso'),
272
+				$version
273
+			);
274
+		$error_message = sprintf(
275
+			esc_html__('%1$s was called %2$sincorrectly%3$s. %4$s %5$s', 'event_espresso'),
276
+			$function,
277
+			'<strong>',
278
+			'</strong>',
279
+			$message,
280
+			$version
281
+		);
282
+		// don't trigger error if doing ajax,
283
+		// instead we'll add a transient EE_Error notice that in theory should show on the next request.
284
+		if (defined('DOING_AJAX') && DOING_AJAX) {
285
+			$error_message .= ' ' . esc_html__(
286
+				'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
287
+				'event_espresso'
288
+			);
289
+			$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
290
+			$error_message .= '<ul><li>';
291
+			$error_message .= implode('</li><li>', $request->requestParams());
292
+			$error_message .= '</ul>';
293
+			EE_Error::add_error($error_message, 'debug::doing_it_wrong', $function, '42');
294
+			// now we set this on the transient so it shows up on the next request.
295
+			EE_Error::get_notices(false, true);
296
+		} else {
297
+			trigger_error($error_message, $error_type);
298
+		}
299
+	}
300
+
301
+
302
+
303
+
304
+	/**
305
+	 * Logger helpers
306
+	 */
307
+	/**
308
+	 * debug
309
+	 *
310
+	 * @param string $class
311
+	 * @param string $func
312
+	 * @param string $line
313
+	 * @param array  $info
314
+	 * @param bool   $display_request
315
+	 * @param string $debug_index
316
+	 * @param string $debug_key
317
+	 */
318
+	public static function log(
319
+		$class = '',
320
+		$func = '',
321
+		$line = '',
322
+		$info = array(),
323
+		$display_request = false,
324
+		$debug_index = '',
325
+		$debug_key = 'EE_DEBUG_SPCO'
326
+	) {
327
+		if (defined('WP_DEBUG') && WP_DEBUG) {
328
+			$debug_key = $debug_key . '_' . EE_Session::instance()->id();
329
+			$debug_data = get_option($debug_key, array());
330
+			$default_data = array(
331
+				$class => $func . '() : ' . $line,
332
+			);
333
+			// don't serialize objects
334
+			$info = self::strip_objects($info);
335
+			$index = ! empty($debug_index) ? $debug_index : 0;
336
+			if (! isset($debug_data[ $index ])) {
337
+				$debug_data[ $index ] = array();
338
+			}
339
+			$debug_data[ $index ][ microtime() ] = array_merge($default_data, $info);
340
+			update_option($debug_key, $debug_data);
341
+		}
342
+	}
343
+
344
+
345
+
346
+	/**
347
+	 * strip_objects
348
+	 *
349
+	 * @param array $info
350
+	 * @return array
351
+	 */
352
+	public static function strip_objects($info = array())
353
+	{
354
+		foreach ($info as $key => $value) {
355
+			if (is_array($value)) {
356
+				$info[ $key ] = self::strip_objects($value);
357
+			} elseif (is_object($value)) {
358
+				$object_class = get_class($value);
359
+				$info[ $object_class ] = array();
360
+				$info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
361
+				if (method_exists($value, 'ID')) {
362
+					$info[ $object_class ]['ID'] = $value->ID();
363
+				}
364
+				if (method_exists($value, 'status')) {
365
+					$info[ $object_class ]['status'] = $value->status();
366
+				} elseif (method_exists($value, 'status_ID')) {
367
+					$info[ $object_class ]['status'] = $value->status_ID();
368
+				}
369
+				unset($info[ $key ]);
370
+			}
371
+		}
372
+		return (array) $info;
373
+	}
374
+
375
+
376
+
377
+	/**
378
+	 * @param mixed      $var
379
+	 * @param string     $var_name
380
+	 * @param string     $file
381
+	 * @param int|string $line
382
+	 * @param int|string $heading_tag
383
+	 * @param bool       $die
384
+	 * @param string     $margin
385
+	 */
386
+	public static function printv(
387
+		$var,
388
+		$var_name = '',
389
+		$file = '',
390
+		$line = '',
391
+		$heading_tag = 5,
392
+		$die = false,
393
+		$margin = ''
394
+	) {
395
+		$var_name = ! $var_name ? 'string' : $var_name;
396
+		$var_name = ucwords(str_replace('$', '', $var_name));
397
+		$is_method = method_exists($var_name, $var);
398
+		$var_name = ucwords(str_replace('_', ' ', $var_name));
399
+		$heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
400
+		// $result = EEH_Debug_Tools::headingSpacer($heading_tag);
401
+		$result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
402
+		$result .= $is_method
403
+			? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
404
+			: EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
405
+		$result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
406
+		$result .= EEH_Debug_Tools::headingX($heading_tag);
407
+		if ($die) {
408
+			die($result);
409
+		}
410
+		echo defined('WP_DEBUG') && WP_DEBUG ? $result : '';
411
+	}
412
+
413
+
414
+	protected static function headingTag($heading_tag)
415
+	{
416
+		$heading_tag = absint($heading_tag);
417
+		return $heading_tag > 0 && $heading_tag < 7 ? "h{$heading_tag}" : 'h5';
418
+	}
419
+
420
+	protected static function headingSpacer($heading_tag)
421
+	{
422
+		return EEH_Debug_Tools::plainOutput() && ($heading_tag === 'h1' || $heading_tag === 'h2')
423
+			? self::lineBreak()
424
+			: '';
425
+	}
426
+
427
+
428
+	protected static function plainOutput()
429
+	{
430
+		return defined('EE_TESTS_DIR')
431
+			   || (defined('DOING_AJAX') && DOING_AJAX && ! isset($_REQUEST['pretty_output']))
432
+			   || (
433
+				   isset($_SERVER['REQUEST_URI'])
434
+				   && strpos(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), 'wp-json') !== false
435
+			   );
436
+	}
437
+
438
+
439
+	/**
440
+	 * @param string $var_name
441
+	 * @param string $heading_tag
442
+	 * @param string $margin
443
+	 * @param int    $line
444
+	 * @return string
445
+	 */
446
+	protected static function heading($var_name = '', $heading_tag = 'h5', $margin = '', $line = 0)
447
+	{
448
+		if (EEH_Debug_Tools::plainOutput()) {
449
+			switch ($heading_tag) {
450
+				case 'h1':
451
+					$line_breaks = EEH_Debug_Tools::lineBreak(3);
452
+					break;
453
+				case 'h2':
454
+					$line_breaks = EEH_Debug_Tools::lineBreak(2);
455
+					break;
456
+				default:
457
+					$line_breaks = EEH_Debug_Tools::lineBreak();
458
+					break;
459
+			}
460
+			return "{$line_breaks}{$line}) {$var_name}";
461
+		}
462
+		$margin = "1rem 1rem .5rem {$margin}";
463
+		return '
464 464
         <' . $heading_tag . ' style="color:#2EA2CC; margin:' . $margin . '; position: sticky;">
465 465
             <b>' . $var_name . '</b>';
466
-    }
466
+	}
467 467
 
468 468
 
469 469
 
470
-    /**
471
-     * @param string $heading_tag
472
-     * @return string
473
-     */
474
-    protected static function headingX($heading_tag = 'h5')
475
-    {
476
-        if (EEH_Debug_Tools::plainOutput()) {
477
-            return '';
478
-        }
479
-        return '
470
+	/**
471
+	 * @param string $heading_tag
472
+	 * @return string
473
+	 */
474
+	protected static function headingX($heading_tag = 'h5')
475
+	{
476
+		if (EEH_Debug_Tools::plainOutput()) {
477
+			return '';
478
+		}
479
+		return '
480 480
         </' . $heading_tag . '>';
481
-    }
482
-
483
-
484
-
485
-    /**
486
-     * @param string $content
487
-     * @return string
488
-     */
489
-    protected static function grey_span($content = '')
490
-    {
491
-        if (EEH_Debug_Tools::plainOutput()) {
492
-            return $content;
493
-        }
494
-        return '<span style="color:#999">' . $content . '</span>';
495
-    }
496
-
497
-
498
-
499
-    /**
500
-     * @param string $file
501
-     * @param int    $line
502
-     * @return string
503
-     */
504
-    protected static function file_and_line($file, $line, $heading_tag)
505
-    {
506
-        if ($file === '' || $line === '') {
507
-            return '';
508
-        }
509
-        $file = str_replace(EE_PLUGIN_DIR_PATH, '/', $file);
510
-        if (EEH_Debug_Tools::plainOutput()) {
511
-            if ($heading_tag === 'h1' || $heading_tag === 'h2') {
512
-                return " ({$file})" . EEH_Debug_Tools::lineBreak();
513
-            }
514
-            return '';
515
-        }
516
-        return EEH_Debug_Tools::lineBreak()
517
-               . '<span style="font-size:9px;font-weight:normal;color:#666;line-height: 12px;">'
518
-               . $file
519
-               . EEH_Debug_Tools::lineBreak()
520
-               . 'line no: '
521
-               . $line
522
-               . '</span>';
523
-    }
524
-
525
-
526
-
527
-    /**
528
-     * @param string $content
529
-     * @return string
530
-     */
531
-    protected static function orange_span($content = '')
532
-    {
533
-        if (EEH_Debug_Tools::plainOutput()) {
534
-            return $content;
535
-        }
536
-        return '<span style="color:#E76700">' . $content . '</span>';
537
-    }
538
-
539
-
540
-
541
-    /**
542
-     * @param mixed $var
543
-     * @return string
544
-     */
545
-    protected static function pre_span($var)
546
-    {
547
-        ob_start();
548
-        if ($var instanceof EE_Base_class) {
549
-            $var->debug();
550
-        } else {
551
-            var_dump($var);
552
-        }
553
-        $var = ob_get_clean();
554
-        if (EEH_Debug_Tools::plainOutput()) {
555
-            return rtrim($var, "\n");
556
-        }
557
-        $style = [
558
-            'background: #334',
559
-            'color: #9C3',
560
-            'display: inline-block',
561
-            'padding: .4em .6em',
562
-        ];
563
-        return '<pre style="' . implode('; ', $style) . '">' . $var . '</pre>';
564
-    }
565
-
566
-
567
-
568
-    /**
569
-     * @param mixed      $var
570
-     * @param string     $var_name
571
-     * @param string     $file
572
-     * @param int|string $line
573
-     * @param int|string $heading_tag
574
-     * @param bool       $die
575
-     */
576
-    public static function printr(
577
-        $var,
578
-        $var_name = '',
579
-        $file = '',
580
-        $line = '',
581
-        $heading_tag = 5,
582
-        $die = false
583
-    ) {
584
-        // return;
585
-        $file = str_replace(rtrim(ABSPATH, '\\/'), '', $file);
586
-        if (empty($var) && empty($var_name)) {
587
-            $var = $file;
588
-            $var_name = "line $line";
589
-            $file = '';
590
-            $line = '';
591
-        }
592
-        $margin = is_admin() ? '180px' : '2rem';
593
-        if (is_string($var)) {
594
-            EEH_Debug_Tools::printv($var, $var_name, $file, $line, $heading_tag, $die, $margin);
595
-            return;
596
-        }
597
-        if (is_object($var)) {
598
-            $var_name = ! $var_name ? 'object' : $var_name;
599
-        } elseif (is_array($var)) {
600
-            $var_name = ! $var_name ? 'array' : $var_name;
601
-        } elseif (is_numeric($var)) {
602
-            $var_name = ! $var_name ? 'numeric' : $var_name;
603
-        } elseif ($var === null) {
604
-            $var_name = ! $var_name ? 'null' : $var_name;
605
-        }
606
-        $var_name = EEH_Debug_Tools::trimVarName($var_name);
607
-        $heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
608
-        // $result = EEH_Debug_Tools::headingSpacer($heading_tag);
609
-        $result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
610
-        $result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
611
-            EEH_Debug_Tools::pre_span($var)
612
-        );
613
-        $result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
614
-        $result .= EEH_Debug_Tools::headingX($heading_tag);
615
-        if ($die) {
616
-            die($result);
617
-        }
618
-        echo defined('WP_DEBUG') && WP_DEBUG ? $result : '';
619
-    }
620
-
621
-
622
-    private static function trimVarName($var_name): string
623
-    {
624
-        $converted = str_replace(['$', '_', 'this->'], ['', ' ', ''], $var_name);
625
-        $words = explode(' ', $converted);
626
-        $words = array_map(
627
-            function ($word) {
628
-                return $word === 'id' || $word === 'Id' ? 'ID' : $word;
629
-            },
630
-            $words
631
-        );
632
-        return ucwords(implode(' ', $words));
633
-    }
634
-
635
-
636
-    private static function lineBreak($lines = 1): string
637
-    {
638
-        $linebreak = defined('DOING_AJAX') && DOING_AJAX ? '<br />' : PHP_EOL;
639
-        return str_repeat($linebreak, $lines);
640
-    }
641
-
642
-
643
-    public static function shortClassName(string $fqcn): string
644
-    {
645
-        return substr(strrchr($fqcn, '\\'), 1);
646
-    }
647
-
648
-
649
-
650
-    /******************** deprecated ********************/
651
-
652
-
653
-
654
-    /**
655
-     * @deprecated 4.9.39.rc.034
656
-     */
657
-    public function reset_times()
658
-    {
659
-        Benchmark::resetTimes();
660
-    }
661
-
662
-
663
-
664
-    /**
665
-     * @deprecated 4.9.39.rc.034
666
-     * @param null $timer_name
667
-     */
668
-    public function start_timer($timer_name = null)
669
-    {
670
-        Benchmark::startTimer($timer_name);
671
-    }
672
-
673
-
674
-
675
-    /**
676
-     * @deprecated 4.9.39.rc.034
677
-     * @param string $timer_name
678
-     */
679
-    public function stop_timer($timer_name = '')
680
-    {
681
-        Benchmark::stopTimer($timer_name);
682
-    }
683
-
684
-
685
-
686
-    /**
687
-     * @deprecated 4.9.39.rc.034
688
-     * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
689
-     * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
690
-     * @return void
691
-     */
692
-    public function measure_memory($label, $output_now = false)
693
-    {
694
-        Benchmark::measureMemory($label, $output_now);
695
-    }
696
-
697
-
698
-
699
-    /**
700
-     * @deprecated 4.9.39.rc.034
701
-     * @param int $size
702
-     * @return string
703
-     */
704
-    public function convert($size)
705
-    {
706
-        return Benchmark::convert($size);
707
-    }
708
-
709
-
481
+	}
482
+
483
+
484
+
485
+	/**
486
+	 * @param string $content
487
+	 * @return string
488
+	 */
489
+	protected static function grey_span($content = '')
490
+	{
491
+		if (EEH_Debug_Tools::plainOutput()) {
492
+			return $content;
493
+		}
494
+		return '<span style="color:#999">' . $content . '</span>';
495
+	}
496
+
497
+
498
+
499
+	/**
500
+	 * @param string $file
501
+	 * @param int    $line
502
+	 * @return string
503
+	 */
504
+	protected static function file_and_line($file, $line, $heading_tag)
505
+	{
506
+		if ($file === '' || $line === '') {
507
+			return '';
508
+		}
509
+		$file = str_replace(EE_PLUGIN_DIR_PATH, '/', $file);
510
+		if (EEH_Debug_Tools::plainOutput()) {
511
+			if ($heading_tag === 'h1' || $heading_tag === 'h2') {
512
+				return " ({$file})" . EEH_Debug_Tools::lineBreak();
513
+			}
514
+			return '';
515
+		}
516
+		return EEH_Debug_Tools::lineBreak()
517
+			   . '<span style="font-size:9px;font-weight:normal;color:#666;line-height: 12px;">'
518
+			   . $file
519
+			   . EEH_Debug_Tools::lineBreak()
520
+			   . 'line no: '
521
+			   . $line
522
+			   . '</span>';
523
+	}
524
+
525
+
526
+
527
+	/**
528
+	 * @param string $content
529
+	 * @return string
530
+	 */
531
+	protected static function orange_span($content = '')
532
+	{
533
+		if (EEH_Debug_Tools::plainOutput()) {
534
+			return $content;
535
+		}
536
+		return '<span style="color:#E76700">' . $content . '</span>';
537
+	}
538
+
539
+
540
+
541
+	/**
542
+	 * @param mixed $var
543
+	 * @return string
544
+	 */
545
+	protected static function pre_span($var)
546
+	{
547
+		ob_start();
548
+		if ($var instanceof EE_Base_class) {
549
+			$var->debug();
550
+		} else {
551
+			var_dump($var);
552
+		}
553
+		$var = ob_get_clean();
554
+		if (EEH_Debug_Tools::plainOutput()) {
555
+			return rtrim($var, "\n");
556
+		}
557
+		$style = [
558
+			'background: #334',
559
+			'color: #9C3',
560
+			'display: inline-block',
561
+			'padding: .4em .6em',
562
+		];
563
+		return '<pre style="' . implode('; ', $style) . '">' . $var . '</pre>';
564
+	}
565
+
566
+
567
+
568
+	/**
569
+	 * @param mixed      $var
570
+	 * @param string     $var_name
571
+	 * @param string     $file
572
+	 * @param int|string $line
573
+	 * @param int|string $heading_tag
574
+	 * @param bool       $die
575
+	 */
576
+	public static function printr(
577
+		$var,
578
+		$var_name = '',
579
+		$file = '',
580
+		$line = '',
581
+		$heading_tag = 5,
582
+		$die = false
583
+	) {
584
+		// return;
585
+		$file = str_replace(rtrim(ABSPATH, '\\/'), '', $file);
586
+		if (empty($var) && empty($var_name)) {
587
+			$var = $file;
588
+			$var_name = "line $line";
589
+			$file = '';
590
+			$line = '';
591
+		}
592
+		$margin = is_admin() ? '180px' : '2rem';
593
+		if (is_string($var)) {
594
+			EEH_Debug_Tools::printv($var, $var_name, $file, $line, $heading_tag, $die, $margin);
595
+			return;
596
+		}
597
+		if (is_object($var)) {
598
+			$var_name = ! $var_name ? 'object' : $var_name;
599
+		} elseif (is_array($var)) {
600
+			$var_name = ! $var_name ? 'array' : $var_name;
601
+		} elseif (is_numeric($var)) {
602
+			$var_name = ! $var_name ? 'numeric' : $var_name;
603
+		} elseif ($var === null) {
604
+			$var_name = ! $var_name ? 'null' : $var_name;
605
+		}
606
+		$var_name = EEH_Debug_Tools::trimVarName($var_name);
607
+		$heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
608
+		// $result = EEH_Debug_Tools::headingSpacer($heading_tag);
609
+		$result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
610
+		$result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
611
+			EEH_Debug_Tools::pre_span($var)
612
+		);
613
+		$result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
614
+		$result .= EEH_Debug_Tools::headingX($heading_tag);
615
+		if ($die) {
616
+			die($result);
617
+		}
618
+		echo defined('WP_DEBUG') && WP_DEBUG ? $result : '';
619
+	}
620
+
621
+
622
+	private static function trimVarName($var_name): string
623
+	{
624
+		$converted = str_replace(['$', '_', 'this->'], ['', ' ', ''], $var_name);
625
+		$words = explode(' ', $converted);
626
+		$words = array_map(
627
+			function ($word) {
628
+				return $word === 'id' || $word === 'Id' ? 'ID' : $word;
629
+			},
630
+			$words
631
+		);
632
+		return ucwords(implode(' ', $words));
633
+	}
634
+
635
+
636
+	private static function lineBreak($lines = 1): string
637
+	{
638
+		$linebreak = defined('DOING_AJAX') && DOING_AJAX ? '<br />' : PHP_EOL;
639
+		return str_repeat($linebreak, $lines);
640
+	}
641
+
642
+
643
+	public static function shortClassName(string $fqcn): string
644
+	{
645
+		return substr(strrchr($fqcn, '\\'), 1);
646
+	}
647
+
648
+
649
+
650
+	/******************** deprecated ********************/
651
+
652
+
653
+
654
+	/**
655
+	 * @deprecated 4.9.39.rc.034
656
+	 */
657
+	public function reset_times()
658
+	{
659
+		Benchmark::resetTimes();
660
+	}
661
+
662
+
663
+
664
+	/**
665
+	 * @deprecated 4.9.39.rc.034
666
+	 * @param null $timer_name
667
+	 */
668
+	public function start_timer($timer_name = null)
669
+	{
670
+		Benchmark::startTimer($timer_name);
671
+	}
672
+
673
+
674
+
675
+	/**
676
+	 * @deprecated 4.9.39.rc.034
677
+	 * @param string $timer_name
678
+	 */
679
+	public function stop_timer($timer_name = '')
680
+	{
681
+		Benchmark::stopTimer($timer_name);
682
+	}
683
+
684
+
685
+
686
+	/**
687
+	 * @deprecated 4.9.39.rc.034
688
+	 * @param string  $label      The label to show for this time eg "Start of calling Some_Class::some_function"
689
+	 * @param boolean $output_now whether to echo now, or wait until EEH_Debug_Tools::show_times() is called
690
+	 * @return void
691
+	 */
692
+	public function measure_memory($label, $output_now = false)
693
+	{
694
+		Benchmark::measureMemory($label, $output_now);
695
+	}
696
+
697
+
698
+
699
+	/**
700
+	 * @deprecated 4.9.39.rc.034
701
+	 * @param int $size
702
+	 * @return string
703
+	 */
704
+	public function convert($size)
705
+	{
706
+		return Benchmark::convert($size);
707
+	}
708
+
709
+
710 710
 
711
-    /**
712
-     * @deprecated 4.9.39.rc.034
713
-     * @param bool $output_now
714
-     * @return string
715
-     */
716
-    public function show_times($output_now = true)
717
-    {
718
-        return Benchmark::displayResults($output_now);
719
-    }
711
+	/**
712
+	 * @deprecated 4.9.39.rc.034
713
+	 * @param bool $output_now
714
+	 * @return string
715
+	 */
716
+	public function show_times($output_now = true)
717
+	{
718
+		return Benchmark::displayResults($output_now);
719
+	}
720 720
 
721 721
 
722 722
 
723
-    /**
724
-     * @deprecated 4.9.39.rc.034
725
-     * @param string $timer_name
726
-     * @param float  $total_time
727
-     * @return string
728
-     */
729
-    public function format_time($timer_name, $total_time)
730
-    {
731
-        return Benchmark::formatTime($timer_name, $total_time);
732
-    }
723
+	/**
724
+	 * @deprecated 4.9.39.rc.034
725
+	 * @param string $timer_name
726
+	 * @param float  $total_time
727
+	 * @return string
728
+	 */
729
+	public function format_time($timer_name, $total_time)
730
+	{
731
+		return Benchmark::formatTime($timer_name, $total_time);
732
+	}
733 733
 }
734 734
 
735 735
 
@@ -739,31 +739,31 @@  discard block
 block discarded – undo
739 739
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
740 740
  */
741 741
 if (class_exists('Kint') && ! function_exists('dump_wp_query')) {
742
-    function dump_wp_query()
743
-    {
744
-        global $wp_query;
745
-        d($wp_query);
746
-    }
742
+	function dump_wp_query()
743
+	{
744
+		global $wp_query;
745
+		d($wp_query);
746
+	}
747 747
 }
748 748
 /**
749 749
  * borrowed from Kint Debugger
750 750
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
751 751
  */
752 752
 if (class_exists('Kint') && ! function_exists('dump_wp')) {
753
-    function dump_wp()
754
-    {
755
-        global $wp;
756
-        d($wp);
757
-    }
753
+	function dump_wp()
754
+	{
755
+		global $wp;
756
+		d($wp);
757
+	}
758 758
 }
759 759
 /**
760 760
  * borrowed from Kint Debugger
761 761
  * Plugin URI: http://upthemes.com/plugins/kint-debugger/
762 762
  */
763 763
 if (class_exists('Kint') && ! function_exists('dump_post')) {
764
-    function dump_post()
765
-    {
766
-        global $post;
767
-        d($post);
768
-    }
764
+	function dump_post()
765
+	{
766
+		global $post;
767
+		d($post);
768
+	}
769 769
 }
Please login to merge, or discard this patch.
Spacing   +42 added lines, -42 removed lines patch added patch discarded remove patch
@@ -37,7 +37,7 @@  discard block
 block discarded – undo
37 37
     public static function instance()
38 38
     {
39 39
         // check if class object is instantiated, and instantiated properly
40
-        if (! self::$_instance instanceof EEH_Debug_Tools) {
40
+        if ( ! self::$_instance instanceof EEH_Debug_Tools) {
41 41
             self::$_instance = new self();
42 42
         }
43 43
         return self::$_instance;
@@ -54,14 +54,14 @@  discard block
 block discarded – undo
54 54
         if (
55 55
             defined('EE_LOAD_KINT')
56 56
             && ! class_exists('Kint')
57
-            && file_exists(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php')
57
+            && file_exists(EE_PLUGIN_DIR_PATH.'tests/kint/Kint.class.php')
58 58
         ) {
59 59
             // despite EE4 having a check for an existing copy of the Kint debugging class,
60 60
             // if another plugin was loaded AFTER EE4 and they did NOT perform a similar check,
61 61
             // then hilarity would ensue as PHP throws a "Cannot redeclare class Kint" error
62 62
             // so we've moved it to our test folder so that it is not included with production releases
63 63
             // plz use https://wordpress.org/plugins/kint-debugger/  if testing production versions of EE
64
-            require_once(EE_PLUGIN_DIR_PATH . 'tests/kint/Kint.class.php');
64
+            require_once(EE_PLUGIN_DIR_PATH.'tests/kint/Kint.class.php');
65 65
         }
66 66
         $plugin = basename(EE_PLUGIN_DIR_PATH);
67 67
         add_action("activate_{$plugin}", array('EEH_Debug_Tools', 'ee_plugin_activation_errors'));
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
      */
79 79
     public static function show_db_name()
80 80
     {
81
-        if (! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
81
+        if ( ! defined('DOING_AJAX') && (defined('EE_ERROR_EMAILS') && EE_ERROR_EMAILS)) {
82 82
             echo '<p style="font-size:10px;font-weight:normal;color:#E76700;margin: 1em 2em; text-align: right;">DB_NAME: '
83 83
                  . DB_NAME
84 84
                  . '</p>';
@@ -128,12 +128,12 @@  discard block
 block discarded – undo
128 128
         global $wp_filter;
129 129
         echo '<br/><br/><br/><h3>Hooked Functions</h3>';
130 130
         if ($tag) {
131
-            $hook[ $tag ] = $wp_filter[ $tag ];
132
-            if (! is_array($hook[ $tag ])) {
131
+            $hook[$tag] = $wp_filter[$tag];
132
+            if ( ! is_array($hook[$tag])) {
133 133
                 trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
134 134
                 return;
135 135
             }
136
-            echo '<h5>For Tag: ' . esc_html($tag) . '</h5>';
136
+            echo '<h5>For Tag: '.esc_html($tag).'</h5>';
137 137
         } else {
138 138
             $hook = is_array($wp_filter) ? $wp_filter : array($wp_filter);
139 139
             ksort($hook);
@@ -163,12 +163,12 @@  discard block
 block discarded – undo
163 163
     {
164 164
         $filters = array();
165 165
         global $wp_filter;
166
-        if (isset($wp_filter[ $hook_name ])) {
167
-            $filters[ $hook_name ] = array();
168
-            foreach ($wp_filter[ $hook_name ] as $priority => $callbacks) {
169
-                $filters[ $hook_name ][ $priority ] = array();
166
+        if (isset($wp_filter[$hook_name])) {
167
+            $filters[$hook_name] = array();
168
+            foreach ($wp_filter[$hook_name] as $priority => $callbacks) {
169
+                $filters[$hook_name][$priority] = array();
170 170
                 foreach ($callbacks as $callback) {
171
-                    $filters[ $hook_name ][ $priority ][] = $callback['function'];
171
+                    $filters[$hook_name][$priority][] = $callback['function'];
172 172
                 }
173 173
             }
174 174
         }
@@ -190,15 +190,15 @@  discard block
 block discarded – undo
190 190
             if (empty($activation_errors)) {
191 191
                 return;
192 192
             }
193
-            $activation_errors = date('Y-m-d H:i:s') . "\n" . $activation_errors;
194
-            espresso_load_required('EEH_File', EE_HELPERS . 'EEH_File.helper.php');
193
+            $activation_errors = date('Y-m-d H:i:s')."\n".$activation_errors;
194
+            espresso_load_required('EEH_File', EE_HELPERS.'EEH_File.helper.php');
195 195
             if (class_exists('EEH_File')) {
196 196
                 try {
197 197
                     EEH_File::ensure_file_exists_and_is_writable(
198
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html'
198
+                        EVENT_ESPRESSO_UPLOAD_DIR.'logs/espresso_plugin_activation_errors.html'
199 199
                     );
200 200
                     EEH_File::write_to_file(
201
-                        EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
201
+                        EVENT_ESPRESSO_UPLOAD_DIR.'logs/espresso_plugin_activation_errors.html',
202 202
                         $activation_errors
203 203
                     );
204 204
                 } catch (EE_Error $e) {
@@ -218,11 +218,11 @@  discard block
 block discarded – undo
218 218
             } else {
219 219
                 // old school attempt
220 220
                 file_put_contents(
221
-                    EVENT_ESPRESSO_UPLOAD_DIR . 'logs/espresso_plugin_activation_errors.html',
221
+                    EVENT_ESPRESSO_UPLOAD_DIR.'logs/espresso_plugin_activation_errors.html',
222 222
                     $activation_errors
223 223
                 );
224 224
             }
225
-            $activation_errors = get_option('ee_plugin_activation_errors', '') . $activation_errors;
225
+            $activation_errors = get_option('ee_plugin_activation_errors', '').$activation_errors;
226 226
             update_option('ee_plugin_activation_errors', $activation_errors);
227 227
         }
228 228
     }
@@ -282,7 +282,7 @@  discard block
 block discarded – undo
282 282
         // don't trigger error if doing ajax,
283 283
         // instead we'll add a transient EE_Error notice that in theory should show on the next request.
284 284
         if (defined('DOING_AJAX') && DOING_AJAX) {
285
-            $error_message .= ' ' . esc_html__(
285
+            $error_message .= ' '.esc_html__(
286 286
                 'This is a doing_it_wrong message that was triggered during an ajax request.  The request params on this request were: ',
287 287
                 'event_espresso'
288 288
             );
@@ -325,18 +325,18 @@  discard block
 block discarded – undo
325 325
         $debug_key = 'EE_DEBUG_SPCO'
326 326
     ) {
327 327
         if (defined('WP_DEBUG') && WP_DEBUG) {
328
-            $debug_key = $debug_key . '_' . EE_Session::instance()->id();
328
+            $debug_key = $debug_key.'_'.EE_Session::instance()->id();
329 329
             $debug_data = get_option($debug_key, array());
330 330
             $default_data = array(
331
-                $class => $func . '() : ' . $line,
331
+                $class => $func.'() : '.$line,
332 332
             );
333 333
             // don't serialize objects
334 334
             $info = self::strip_objects($info);
335 335
             $index = ! empty($debug_index) ? $debug_index : 0;
336
-            if (! isset($debug_data[ $index ])) {
337
-                $debug_data[ $index ] = array();
336
+            if ( ! isset($debug_data[$index])) {
337
+                $debug_data[$index] = array();
338 338
             }
339
-            $debug_data[ $index ][ microtime() ] = array_merge($default_data, $info);
339
+            $debug_data[$index][microtime()] = array_merge($default_data, $info);
340 340
             update_option($debug_key, $debug_data);
341 341
         }
342 342
     }
@@ -353,20 +353,20 @@  discard block
 block discarded – undo
353 353
     {
354 354
         foreach ($info as $key => $value) {
355 355
             if (is_array($value)) {
356
-                $info[ $key ] = self::strip_objects($value);
356
+                $info[$key] = self::strip_objects($value);
357 357
             } elseif (is_object($value)) {
358 358
                 $object_class = get_class($value);
359
-                $info[ $object_class ] = array();
360
-                $info[ $object_class ]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
359
+                $info[$object_class] = array();
360
+                $info[$object_class]['ID'] = method_exists($value, 'ID') ? $value->ID() : spl_object_hash($value);
361 361
                 if (method_exists($value, 'ID')) {
362
-                    $info[ $object_class ]['ID'] = $value->ID();
362
+                    $info[$object_class]['ID'] = $value->ID();
363 363
                 }
364 364
                 if (method_exists($value, 'status')) {
365
-                    $info[ $object_class ]['status'] = $value->status();
365
+                    $info[$object_class]['status'] = $value->status();
366 366
                 } elseif (method_exists($value, 'status_ID')) {
367
-                    $info[ $object_class ]['status'] = $value->status_ID();
367
+                    $info[$object_class]['status'] = $value->status_ID();
368 368
                 }
369
-                unset($info[ $key ]);
369
+                unset($info[$key]);
370 370
             }
371 371
         }
372 372
         return (array) $info;
@@ -400,8 +400,8 @@  discard block
 block discarded – undo
400 400
         // $result = EEH_Debug_Tools::headingSpacer($heading_tag);
401 401
         $result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
402 402
         $result .= $is_method
403
-            ? EEH_Debug_Tools::grey_span('::') . EEH_Debug_Tools::orange_span($var . '()')
404
-            : EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span($var);
403
+            ? EEH_Debug_Tools::grey_span('::').EEH_Debug_Tools::orange_span($var.'()')
404
+            : EEH_Debug_Tools::grey_span(' : ').EEH_Debug_Tools::orange_span($var);
405 405
         $result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
406 406
         $result .= EEH_Debug_Tools::headingX($heading_tag);
407 407
         if ($die) {
@@ -461,8 +461,8 @@  discard block
 block discarded – undo
461 461
         }
462 462
         $margin = "1rem 1rem .5rem {$margin}";
463 463
         return '
464
-        <' . $heading_tag . ' style="color:#2EA2CC; margin:' . $margin . '; position: sticky;">
465
-            <b>' . $var_name . '</b>';
464
+        <' . $heading_tag.' style="color:#2EA2CC; margin:'.$margin.'; position: sticky;">
465
+            <b>' . $var_name.'</b>';
466 466
     }
467 467
 
468 468
 
@@ -477,7 +477,7 @@  discard block
 block discarded – undo
477 477
             return '';
478 478
         }
479 479
         return '
480
-        </' . $heading_tag . '>';
480
+        </' . $heading_tag.'>';
481 481
     }
482 482
 
483 483
 
@@ -491,7 +491,7 @@  discard block
 block discarded – undo
491 491
         if (EEH_Debug_Tools::plainOutput()) {
492 492
             return $content;
493 493
         }
494
-        return '<span style="color:#999">' . $content . '</span>';
494
+        return '<span style="color:#999">'.$content.'</span>';
495 495
     }
496 496
 
497 497
 
@@ -509,7 +509,7 @@  discard block
 block discarded – undo
509 509
         $file = str_replace(EE_PLUGIN_DIR_PATH, '/', $file);
510 510
         if (EEH_Debug_Tools::plainOutput()) {
511 511
             if ($heading_tag === 'h1' || $heading_tag === 'h2') {
512
-                return " ({$file})" . EEH_Debug_Tools::lineBreak();
512
+                return " ({$file})".EEH_Debug_Tools::lineBreak();
513 513
             }
514 514
             return '';
515 515
         }
@@ -533,7 +533,7 @@  discard block
 block discarded – undo
533 533
         if (EEH_Debug_Tools::plainOutput()) {
534 534
             return $content;
535 535
         }
536
-        return '<span style="color:#E76700">' . $content . '</span>';
536
+        return '<span style="color:#E76700">'.$content.'</span>';
537 537
     }
538 538
 
539 539
 
@@ -560,7 +560,7 @@  discard block
 block discarded – undo
560 560
             'display: inline-block',
561 561
             'padding: .4em .6em',
562 562
         ];
563
-        return '<pre style="' . implode('; ', $style) . '">' . $var . '</pre>';
563
+        return '<pre style="'.implode('; ', $style).'">'.$var.'</pre>';
564 564
     }
565 565
 
566 566
 
@@ -607,7 +607,7 @@  discard block
 block discarded – undo
607 607
         $heading_tag = EEH_Debug_Tools::headingTag($heading_tag);
608 608
         // $result = EEH_Debug_Tools::headingSpacer($heading_tag);
609 609
         $result = EEH_Debug_Tools::heading($var_name, $heading_tag, $margin, $line);
610
-        $result .= EEH_Debug_Tools::grey_span(' : ') . EEH_Debug_Tools::orange_span(
610
+        $result .= EEH_Debug_Tools::grey_span(' : ').EEH_Debug_Tools::orange_span(
611 611
             EEH_Debug_Tools::pre_span($var)
612 612
         );
613 613
         $result .= EEH_Debug_Tools::file_and_line($file, $line, $heading_tag);
@@ -624,7 +624,7 @@  discard block
 block discarded – undo
624 624
         $converted = str_replace(['$', '_', 'this->'], ['', ' ', ''], $var_name);
625 625
         $words = explode(' ', $converted);
626 626
         $words = array_map(
627
-            function ($word) {
627
+            function($word) {
628 628
                 return $word === 'id' || $word === 'Id' ? 'ID' : $word;
629 629
             },
630 630
             $words
Please login to merge, or discard this patch.
core/helpers/EEH_Template.helper.php 2 patches
Indentation   +953 added lines, -953 removed lines patch added patch discarded remove patch
@@ -9,36 +9,36 @@  discard block
 block discarded – undo
9 9
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
10 10
 
11 11
 if (! function_exists('espresso_get_template_part')) {
12
-    /**
13
-     * espresso_get_template_part
14
-     * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
15
-     * so not a very useful function at all except that it adds familiarity PLUS filtering based off of the entire template part name
16
-     *
17
-     * @param string $slug The slug name for the generic template.
18
-     * @param string $name The name of the specialised template.
19
-     */
20
-    function espresso_get_template_part($slug = '', $name = '')
21
-    {
22
-        EEH_Template::get_template_part($slug, $name);
23
-    }
12
+	/**
13
+	 * espresso_get_template_part
14
+	 * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
15
+	 * so not a very useful function at all except that it adds familiarity PLUS filtering based off of the entire template part name
16
+	 *
17
+	 * @param string $slug The slug name for the generic template.
18
+	 * @param string $name The name of the specialised template.
19
+	 */
20
+	function espresso_get_template_part($slug = '', $name = '')
21
+	{
22
+		EEH_Template::get_template_part($slug, $name);
23
+	}
24 24
 }
25 25
 
26 26
 
27 27
 if (! function_exists('espresso_get_object_css_class')) {
28
-    /**
29
-     * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30
-     *
31
-     * @param EE_Base_Class $object the EE object the css class is being generated for
32
-     * @param string        $prefix added to the beginning of the generated class
33
-     * @param string        $suffix added to the end of the generated class
34
-     * @return string
35
-     * @throws EE_Error
36
-     * @throws ReflectionException
37
-     */
38
-    function espresso_get_object_css_class($object = null, $prefix = '', $suffix = '')
39
-    {
40
-        return EEH_Template::get_object_css_class($object, $prefix, $suffix);
41
-    }
28
+	/**
29
+	 * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30
+	 *
31
+	 * @param EE_Base_Class $object the EE object the css class is being generated for
32
+	 * @param string        $prefix added to the beginning of the generated class
33
+	 * @param string        $suffix added to the end of the generated class
34
+	 * @return string
35
+	 * @throws EE_Error
36
+	 * @throws ReflectionException
37
+	 */
38
+	function espresso_get_object_css_class($object = null, $prefix = '', $suffix = '')
39
+	{
40
+		return EEH_Template::get_object_css_class($object, $prefix, $suffix);
41
+	}
42 42
 }
43 43
 
44 44
 
@@ -52,661 +52,661 @@  discard block
 block discarded – undo
52 52
  */
53 53
 class EEH_Template
54 54
 {
55
-    private static array $_espresso_themes = [];
56
-
57
-
58
-    /**
59
-     *    is_espresso_theme - returns TRUE or FALSE on whether the currently active WP theme is an espresso theme
60
-     *
61
-     * @return boolean
62
-     */
63
-    public static function is_espresso_theme()
64
-    {
65
-        return wp_get_theme()->get('TextDomain') === 'event_espresso';
66
-    }
67
-
68
-
69
-    /**
70
-     *    load_espresso_theme_functions - if current theme is an espresso theme, or uses ee theme template parts, then
71
-     *    load its functions.php file ( if not already loaded )
72
-     *
73
-     * @return void
74
-     */
75
-    public static function load_espresso_theme_functions()
76
-    {
77
-        if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
-            if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
-                require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
80
-            }
81
-        }
82
-    }
83
-
84
-
85
-    /**
86
-     *    get_espresso_themes - returns an array of Espresso Child themes located in the /templates/ directory
87
-     *
88
-     * @return array
89
-     */
90
-    public static function get_espresso_themes(): array
91
-    {
92
-        if (empty(EEH_Template::$_espresso_themes)) {
93
-            $espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
94
-            if (empty($espresso_themes)) {
95
-                return [];
96
-            }
97
-            if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
-                unset($espresso_themes[ $key ]);
99
-            }
100
-            EEH_Template::$_espresso_themes = [];
101
-            foreach ($espresso_themes as $espresso_theme) {
102
-                EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
103
-            }
104
-        }
105
-        return EEH_Template::$_espresso_themes;
106
-    }
107
-
108
-
109
-    /**
110
-     * EEH_Template::get_template_part
111
-     * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead,
112
-     * and doesn't add base versions of files so not a very useful function at all except that it adds familiarity PLUS
113
-     * filtering based off of the entire template part name
114
-     *
115
-     * @param string $slug The slug name for the generic template.
116
-     * @param string $name The name of the specialised template.
117
-     * @param array  $template_args
118
-     * @param bool   $return_string
119
-     * @return string        the html output for the formatted money value
120
-     */
121
-    public static function get_template_part(
122
-        $slug = '',
123
-        $name = '',
124
-        $template_args = [],
125
-        $return_string = false
126
-    ) {
127
-        do_action("get_template_part_$slug-$name", $slug, $name);
128
-        $template = $slug;
129
-        $name      = (string) $name;
130
-        if ($name != '') {
131
-            $template .= "-$name";
132
-        }
133
-        $template .= ".php";
134
-        // allow template parts to be turned off via something like:
135
-        // add_filter( 'FHEE__content_espresso_events_tickets_template__display_datetimes', '__return_false' );
136
-        if (apply_filters("FHEE__EEH_Template__get_template_part__display__{$slug}_$name", true)) {
137
-            return EEH_Template::locate_template($template, $template_args, true, $return_string);
138
-        }
139
-        return '';
140
-    }
141
-
142
-
143
-    /**
144
-     *    locate_template
145
-     *    locate a template file by looking in the following places, in the following order:
146
-     *        <server path up to>/wp-content/themes/<current active WordPress theme>/
147
-     *        <assumed full absolute server path>
148
-     *        <server path up to>/wp-content/uploads/espresso/templates/<current EE theme>/
149
-     *        <server path up to>/wp-content/uploads/espresso/templates/
150
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/public/<current EE theme>/
151
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/core/templates/<current EE theme>/
152
-     *        <server path up to>/wp-content/plugins/<EE4 folder>/
153
-     *    as soon as the template is found in one of these locations, it will be returned or loaded
154
-     *        Example:
155
-     *          You are using the WordPress Twenty Sixteen theme,
156
-     *        and you want to customize the "some-event.template.php" template,
157
-     *          which is located in the "/relative/path/to/" folder relative to the main EE plugin folder.
158
-     *          Assuming WP is installed on your server in the "/home/public_html/" folder,
159
-     *        EEH_Template::locate_template() will look at the following paths in order until the template is found:
160
-     *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
161
-     *        /relative/path/to/some-event.template.php
162
-     *        /home/public_html/wp-content/uploads/espresso/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
163
-     *        /home/public_html/wp-content/uploads/espresso/templates/relative/path/to/some-event.template.php
164
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/public/Espresso_Arabica_2014/relative/path/to/some-event.template.php
165
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/core/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
166
-     *        /home/public_html/wp-content/plugins/event-espresso-core-reg/relative/path/to/some-event.template.php
167
-     *          Had you passed an absolute path to your template that was in some other location,
168
-     *        ie: "/absolute/path/to/some-event.template.php"
169
-     *          then the search would have been :
170
-     *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
171
-     *        /absolute/path/to/some-event.template.php
172
-     *          and stopped there upon finding it in the second location
173
-     *
174
-     * @param array|string $templates       array of template file names including extension (or just a single string)
175
-     * @param array        $template_args   an array of arguments to be extracted for use in the template
176
-     * @param boolean      $load            whether to pass the located template path on to the
177
-     *                                      EEH_Template::display_template() method or simply return it
178
-     * @param boolean      $return_string   whether to send output immediately to screen, or capture and return as a
179
-     *                                      string
180
-     * @param boolean      $check_if_custom If TRUE, this flags this method to return boolean for whether this will
181
-     *                                      generate a custom template or not. Used in places where you don't actually
182
-     *                                      load the template, you just want to know if there's a custom version of it.
183
-     * @return string|true
184
-     * @throws DomainException
185
-     * @throws InvalidArgumentException
186
-     * @throws InvalidDataTypeException
187
-     * @throws InvalidInterfaceException
188
-     */
189
-    public static function locate_template(
190
-        $templates = [],
191
-        array $template_args = [],
192
-        bool $load = true,
193
-        bool $return_string = true,
194
-        bool $check_if_custom = false
195
-    ) {
196
-        $cache_id      = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
197
-        $template_path = TemplateCache::get($cache_id);
198
-        $template_path = $template_path ?: self::resolveTemplatePath($cache_id, (array) $templates, $check_if_custom);
199
-
200
-        if ($check_if_custom && ! empty($template_path)) {
201
-            return true;
202
-        }
203
-
204
-        // if we got it and you want to see it...
205
-        if ($template_path && $load && ! $check_if_custom) {
206
-            if ($return_string) {
207
-                return EEH_Template::display_template($template_path, $template_args, true);
208
-            }
209
-            EEH_Template::display_template($template_path, $template_args);
210
-        }
211
-        return $check_if_custom && ! empty($template_path) ? true : $template_path;
212
-    }
213
-
214
-
215
-    /**
216
-     * Resolves the path of a template by checking various possible locations.
217
-     *
218
-     * This method checks for the existence of a template in several locations,
219
-     * including the current theme folder, the uploads directory, and the plugin's own template directory.
220
-     * It uses the provided cache ID to store and retrieve the resolved path from a cache for performance.
221
-     * If the template is not found in any of the checked locations, an empty string is returned.
222
-     *
223
-     * @param string $cache_id        The ID used for caching the resolved path.
224
-     * @param array  $templates       An array of template file names to search for.
225
-     * @param bool $check_if_custom   If true, the method will only check if a custom template exists
226
-     *                                and won't include core plugin folders.
227
-     * @return string The resolved template path, or an empty string if the template was not found.
228
-     * @since 5.0.21.p
229
-     */
230
-    private static function resolveTemplatePath(string $cache_id, array $templates, bool $check_if_custom): string
231
-    {
232
-        // first use WP locate_template to check for template in the current theme folder
233
-        $template_path = $templates ? locate_template($templates) : '';
234
-        // not in the theme
235
-        if (empty($template_path)) {
236
-            // not even a template to look for ?
237
-            if (empty($templates)) {
238
-                $loader = LoaderFactory::getLoader();
239
-                /** @var RequestInterface $request */
240
-                $request = $loader->getShared(RequestInterface::class);
241
-                // get post_type
242
-                $post_type = $request->getRequestParam('post_type');
243
-                /** @var CustomPostTypeDefinitions $custom_post_types */
244
-                $custom_post_types = $loader->getShared(CustomPostTypeDefinitions::class);
245
-                // get array of EE Custom Post Types
246
-                $EE_CPTs = $custom_post_types->getDefinitions();
247
-                // build template name based on request
248
-                if (isset($EE_CPTs[ $post_type ])) {
249
-                    $archive_or_single = is_archive() ? 'archive' : '';
250
-                    $archive_or_single = is_single() ? 'single' : $archive_or_single;
251
-                    $templates[]       = $archive_or_single . '-' . $post_type . '.php';
252
-                }
253
-            }
254
-            // currently active EE template theme
255
-            $current_theme = EE_Config::get_current_theme();
256
-            // array of paths to folders that may contain templates
257
-            $template_folder_paths = [];
258
-
259
-            // add core plugin folders for checking only if we're not $check_if_custom
260
-            if (! $check_if_custom) {
261
-                $core_paths            = [
262
-                    // in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
-                    EE_PUBLIC . $current_theme,
264
-                    // in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
-                    EE_TEMPLATES . $current_theme,
266
-                    // or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267
-                    EE_PLUGIN_DIR_PATH,
268
-                ];
269
-                $template_folder_paths = array_merge($template_folder_paths, $core_paths);
270
-            }
271
-
272
-            // now filter that array
273
-            $template_folder_paths = (array) apply_filters(
274
-                'FHEE__EEH_Template__locate_template__template_folder_paths',
275
-                $template_folder_paths
276
-            );
277
-
278
-            // array to hold all possible template paths
279
-            $full_template_paths = [];
280
-            $file_name           = '';
281
-
282
-            // loop through $templates
283
-            foreach ($templates as $template) {
284
-                // normalize directory separators
285
-                $template                      = EEH_File::standardise_directory_separators($template);
286
-                $file_name                     = basename($template);
287
-                $template_path_minus_file_name = substr($template, 0, (strlen($file_name) * -1));
288
-                // while looping through all template folder paths
289
-                foreach ($template_folder_paths as $template_folder_path) {
290
-                    // normalize directory separators
291
-                    $template_folder_path = EEH_File::standardise_directory_separators($template_folder_path);
292
-                    // determine if any common base path exists between the two paths
293
-                    $common_base_path = EEH_Template::_find_common_base_path(
294
-                        [$template_folder_path, $template_path_minus_file_name]
295
-                    );
296
-                    if ($common_base_path !== '') {
297
-                        // both paths have a common base, so just tack the filename onto our search path
298
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
299
-                    } else {
300
-                        // no common base path, so let's just concatenate
301
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
302
-                    }
303
-                    // build up our template locations array by adding our resolved paths
304
-                    $full_template_paths[] = $resolved_path;
305
-                }
306
-                // if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307
-                array_unshift($full_template_paths, $template);
308
-                // path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
-                array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
310
-            }
311
-            // filter final array of full template paths
312
-            $full_template_paths = apply_filters(
313
-                'FHEE__EEH_Template__locate_template__full_template_paths',
314
-                $full_template_paths,
315
-                $file_name
316
-            );
317
-            // now loop through our final array of template location paths and check each location
318
-            foreach ((array) $full_template_paths as $full_template_path) {
319
-                if (is_readable($full_template_path)) {
320
-                    $template_path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $full_template_path);
321
-                    TemplateCache::set($cache_id, $template_path);
322
-                    break;
323
-                }
324
-            }
325
-        }
326
-
327
-        // Display a deprecated notice if the template file is located in the WordPress uploads directory
328
-        if (strpos($template_path, 'wp-content/uploads/espresso') !== false) {
329
-            EE_Error::doing_it_wrong(
330
-                __CLASS__,
331
-                esc_html__(
332
-                    'The use of the WordPress uploads directory as a location to override template files has been deprecated.',
333
-                    'event_espresso'
334
-                ),
335
-                '5.0.0'
336
-            );
337
-        }
338
-
339
-        // hook that can be used to display the full template path that will be used
340
-        do_action('AHEE__EEH_Template__locate_template__full_template_path', $template_path);
341
-
342
-        return $template_path;
343
-    }
344
-
345
-
346
-    /**
347
-     * _find_common_base_path
348
-     * given two paths, this determines if there is a common base path between the two
349
-     *
350
-     * @param array $paths
351
-     * @return string
352
-     */
353
-    protected static function _find_common_base_path($paths)
354
-    {
355
-        $last_offset      = 0;
356
-        $common_base_path = '';
357
-        while (($index = strpos($paths[0], '/', $last_offset)) !== false) {
358
-            $dir_length = $index - $last_offset + 1;
359
-            $directory  = substr($paths[0], $last_offset, $dir_length);
360
-            foreach ($paths as $path) {
361
-                if (substr($path, $last_offset, $dir_length) != $directory) {
362
-                    return $common_base_path;
363
-                }
364
-            }
365
-            $common_base_path .= $directory;
366
-            $last_offset      = $index + 1;
367
-        }
368
-        return substr($common_base_path, 0, -1);
369
-    }
370
-
371
-
372
-    /**
373
-     * load and display a template
374
-     *
375
-     * @param bool|string $template_path    server path to the file to be loaded, including file name and extension
376
-     * @param array       $template_args    an array of arguments to be extracted for use in the template
377
-     * @param boolean     $return_string    whether to send output immediately to screen, or capture and return as a
378
-     *                                      string
379
-     * @param bool        $throw_exceptions if set to true, will throw an exception if the template is either
380
-     *                                      not found or is not readable
381
-     * @return string
382
-     * @throws DomainException
383
-     */
384
-    public static function display_template(
385
-        $template_path = '',
386
-        $template_args = [],
387
-        $return_string = false,
388
-        $throw_exceptions = false
389
-    ) {
390
-        /**
391
-         * These two filters are intended for last minute changes to templates being loaded and/or template arg
392
-         * modifications.  NOTE... modifying these things can cause breakage as most templates running through
393
-         * the display_template method are templates we DON'T want modified (usually because of js
394
-         * dependencies etc).  So unless you know what you are doing, do NOT filter templates or template args
395
-         * using this.
396
-         *
397
-         * @since 4.6.0
398
-         */
399
-        $template_path = (string) apply_filters('FHEE__EEH_Template__display_template__template_path', $template_path);
400
-        $template_args = (array) apply_filters('FHEE__EEH_Template__display_template__template_args', $template_args);
401
-
402
-        // you gimme nuttin - YOU GET NUTTIN !!
403
-        if (! $template_path || ! is_readable($template_path)) {
404
-            // ignore whether template is accessible ?
405
-            if ($throw_exceptions) {
406
-                throw new DomainException(
407
-                    esc_html__('Invalid, unreadable, or missing file.', 'event_espresso')
408
-                );
409
-            }
410
-            return '';
411
-        }
412
-
413
-        extract($template_args, EXTR_SKIP);
414
-        // because we might want to return a string, we are going to capture the output
415
-        ob_start();
416
-        include($template_path);
417
-        $template = ob_get_clean();
418
-
419
-        if ($return_string) {
420
-            return $template;
421
-        }
422
-        echo wp_kses($template, AllowedTags::getWithFullTags());
423
-        return '';
424
-    }
425
-
426
-
427
-    /**
428
-     * get_object_css_class - attempts to generate a css class based on the type of EE object passed
429
-     *
430
-     * @param EE_Base_Class $object the EE object the css class is being generated for
431
-     * @param string        $prefix added to the beginning of the generated class
432
-     * @param string        $suffix added to the end of the generated class
433
-     * @return string
434
-     * @throws EE_Error
435
-     * @throws ReflectionException
436
-     */
437
-    public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
438
-    {
439
-        // in the beginning...
440
-        $prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
441
-        // da muddle
442
-        $class = '';
443
-        // the end
444
-        $suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
445
-        // is the passed object an EE object ?
446
-        if ($object instanceof EE_Base_Class) {
447
-            // grab the exact type of object
448
-            $obj_class = get_class($object);
449
-            // depending on the type of object...
450
-            // no specifics just yet...
451
-            $class = strtolower(str_replace('_', '-', $obj_class));
452
-            $class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
453
-        }
454
-        return $prefix . $class . $suffix;
455
-    }
456
-
457
-
458
-    /**
459
-     * EEH_Template::format_currency
460
-     * This helper takes a raw float value and formats it according to the default config country currency settings, or
461
-     * the country currency settings from the supplied country ISO code
462
-     *
463
-     * @param float   $amount       raw money value
464
-     * @param boolean $return_raw   whether to return the formatted float value only with no currency sign or code
465
-     * @param boolean $display_code whether to display the country code (USD). Default = TRUE
466
-     * @param string  $CNT_ISO      2-letter ISO code for a country
467
-     * @param string  $cur_code_span_class
468
-     * @return string        the html output for the formatted money value
469
-     */
470
-    public static function format_currency(
471
-        $amount = null,
472
-        $return_raw = false,
473
-        $display_code = true,
474
-        $CNT_ISO = '',
475
-        $cur_code_span_class = 'currency-code'
476
-    ) {
477
-        // ensure amount was received
478
-        if ($amount === null) {
479
-            $msg = esc_html__('In order to format currency, an amount needs to be passed.', 'event_espresso');
480
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
481
-            return '';
482
-        }
483
-        // ensure amount is float
484
-        $amount  = (float) apply_filters('FHEE__EEH_Template__format_currency__raw_amount', (float) $amount);
485
-        $CNT_ISO = apply_filters('FHEE__EEH_Template__format_currency__CNT_ISO', $CNT_ISO, $amount);
486
-        // filter raw amount (allows 0.00 to be changed to "free" for example)
487
-        $amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
488
-        // still a number, or was amount converted to a string like "free" ?
489
-        if (! is_float($amount_formatted)) {
490
-            return esc_html($amount_formatted);
491
-        }
492
-        try {
493
-            // was a country ISO code passed ? if so generate currency config object for that country
494
-            $mny = $CNT_ISO !== '' ? new EE_Currency_Config($CNT_ISO) : null;
495
-        } catch (Exception $e) {
496
-            // eat exception
497
-            $mny = null;
498
-        }
499
-        // verify results
500
-        if (! $mny instanceof EE_Currency_Config) {
501
-            // set default config country currency settings
502
-            $mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
503
-                ? EE_Registry::instance()->CFG->currency
504
-                : new EE_Currency_Config();
505
-        }
506
-        // format float
507
-        $amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
508
-        // add formatting ?
509
-        if (! $return_raw) {
510
-            // add currency sign
511
-            if ($mny->sign_b4) {
512
-                if ($amount >= 0) {
513
-                    $amount_formatted = $mny->sign . $amount_formatted;
514
-                } else {
515
-                    $amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
516
-                }
517
-            } else {
518
-                $amount_formatted = $amount_formatted . $mny->sign;
519
-            }
520
-
521
-            // filter to allow global setting of display_code
522
-            $display_code = (bool) apply_filters(
523
-                'FHEE__EEH_Template__format_currency__display_code',
524
-                $display_code
525
-            );
526
-
527
-            // add currency code ?
528
-            $amount_formatted = $display_code
529
-                ? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
530
-                : $amount_formatted;
531
-        }
532
-        // filter results
533
-        $amount_formatted = apply_filters(
534
-            'FHEE__EEH_Template__format_currency__amount_formatted',
535
-            $amount_formatted,
536
-            $mny,
537
-            $return_raw
538
-        );
539
-        // clean up vars
540
-        unset($mny);
541
-        // return formatted currency amount
542
-        return $amount_formatted;
543
-    }
544
-
545
-
546
-    /**
547
-     * This function is used for outputting the localized label for a given status id in the schema requested (and
548
-     * possibly plural).  The intended use of this function is only for cases where wanting a label outside of a
549
-     * related status model or model object (i.e. in documentation etc.)
550
-     *
551
-     * @param string  $status_id  Status ID matching a registered status in the esp_status table.  If there is no
552
-     *                            match, then 'Unknown' will be returned.
553
-     * @param boolean $plural     Whether to return plural or not
554
-     * @param string  $schema     'UPPER', 'lower', or 'Sentence'
555
-     * @return string             The localized label for the status id.
556
-     * @throws EE_Error
557
-     */
558
-    public static function pretty_status($status_id, $plural = false, $schema = 'upper')
559
-    {
560
-        $status = EEM_Status::instance()->localized_status(
561
-            [$status_id => esc_html__('unknown', 'event_espresso')],
562
-            $plural,
563
-            $schema
564
-        );
565
-        return $status[ $status_id ];
566
-    }
567
-
568
-
569
-    /**
570
-     * This helper just returns a button or link for the given parameters
571
-     *
572
-     * @param string $url   the url for the link, note that `esc_url` will be called on it
573
-     * @param string $label What is the label you want displayed for the button
574
-     * @param string $class what class is used for the button (defaults to 'button--primary')
575
-     * @param string $icon
576
-     * @param string $title
577
-     * @return string the html output for the button
578
-     */
579
-    public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
580
-    {
581
-        $icon_html = '';
582
-        if (! empty($icon)) {
583
-            $dashicons = preg_split("(ee-icon |dashicons )", $icon);
584
-            $dashicons = array_filter($dashicons);
585
-            $count     = count($dashicons);
586
-            $icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
587
-            foreach ($dashicons as $dashicon) {
588
-                $type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
589
-                $icon_html .= '<span class="' . $type . $dashicon . '"></span>';
590
-            }
591
-            $icon_html .= $count > 1 ? '</span>' : '';
592
-        }
593
-        // sanitize & escape
594
-        $id    = sanitize_title_with_dashes($label);
595
-        $url   = esc_url_raw($url);
596
-        $class = esc_attr($class);
597
-        $title = esc_attr($title);
598
-        $class .= $title ? ' ee-aria-tooltip' : '';
599
-        $title = $title ? " aria-label='{$title}'" : '';
600
-        $label = esc_html($label);
601
-        return "<a id='{$id}' href='{$url}' class='{$class}'{$title}>{$icon_html}{$label}</a>";
602
-    }
603
-
604
-
605
-    /**
606
-     * This returns a generated link that will load the related help tab on admin pages.
607
-     *
608
-     * @param string      $help_tab_id the id for the connected help tab
609
-     * @param bool|string $page        The page identifier for the page the help tab is on
610
-     * @param bool|string $action      The action (route) for the admin page the help tab is on.
611
-     * @param bool|string $icon_style  (optional) include css class for the style you want to use for the help icon.
612
-     * @param bool|string $help_text   (optional) send help text you want to use for the link if default not to be used
613
-     * @return string              generated link
614
-     */
615
-    public static function get_help_tab_link(
616
-        $help_tab_id,
617
-        $page = false,
618
-        $action = false,
619
-        $icon_style = false,
620
-        $help_text = false
621
-    ) {
622
-        /** @var RequestInterface $request */
623
-        $request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
624
-        $page    = $page ?: $request->getRequestParam('page', '', 'key');
625
-        $action  = $action ?: $request->getRequestParam('action', 'default', 'key');
626
-
627
-
628
-        $help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
629
-        $icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
630
-        $help_text    = ! $help_text ? '' : $help_text;
631
-        return '
55
+	private static array $_espresso_themes = [];
56
+
57
+
58
+	/**
59
+	 *    is_espresso_theme - returns TRUE or FALSE on whether the currently active WP theme is an espresso theme
60
+	 *
61
+	 * @return boolean
62
+	 */
63
+	public static function is_espresso_theme()
64
+	{
65
+		return wp_get_theme()->get('TextDomain') === 'event_espresso';
66
+	}
67
+
68
+
69
+	/**
70
+	 *    load_espresso_theme_functions - if current theme is an espresso theme, or uses ee theme template parts, then
71
+	 *    load its functions.php file ( if not already loaded )
72
+	 *
73
+	 * @return void
74
+	 */
75
+	public static function load_espresso_theme_functions()
76
+	{
77
+		if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
+			if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
+				require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
80
+			}
81
+		}
82
+	}
83
+
84
+
85
+	/**
86
+	 *    get_espresso_themes - returns an array of Espresso Child themes located in the /templates/ directory
87
+	 *
88
+	 * @return array
89
+	 */
90
+	public static function get_espresso_themes(): array
91
+	{
92
+		if (empty(EEH_Template::$_espresso_themes)) {
93
+			$espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
94
+			if (empty($espresso_themes)) {
95
+				return [];
96
+			}
97
+			if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
+				unset($espresso_themes[ $key ]);
99
+			}
100
+			EEH_Template::$_espresso_themes = [];
101
+			foreach ($espresso_themes as $espresso_theme) {
102
+				EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
103
+			}
104
+		}
105
+		return EEH_Template::$_espresso_themes;
106
+	}
107
+
108
+
109
+	/**
110
+	 * EEH_Template::get_template_part
111
+	 * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead,
112
+	 * and doesn't add base versions of files so not a very useful function at all except that it adds familiarity PLUS
113
+	 * filtering based off of the entire template part name
114
+	 *
115
+	 * @param string $slug The slug name for the generic template.
116
+	 * @param string $name The name of the specialised template.
117
+	 * @param array  $template_args
118
+	 * @param bool   $return_string
119
+	 * @return string        the html output for the formatted money value
120
+	 */
121
+	public static function get_template_part(
122
+		$slug = '',
123
+		$name = '',
124
+		$template_args = [],
125
+		$return_string = false
126
+	) {
127
+		do_action("get_template_part_$slug-$name", $slug, $name);
128
+		$template = $slug;
129
+		$name      = (string) $name;
130
+		if ($name != '') {
131
+			$template .= "-$name";
132
+		}
133
+		$template .= ".php";
134
+		// allow template parts to be turned off via something like:
135
+		// add_filter( 'FHEE__content_espresso_events_tickets_template__display_datetimes', '__return_false' );
136
+		if (apply_filters("FHEE__EEH_Template__get_template_part__display__{$slug}_$name", true)) {
137
+			return EEH_Template::locate_template($template, $template_args, true, $return_string);
138
+		}
139
+		return '';
140
+	}
141
+
142
+
143
+	/**
144
+	 *    locate_template
145
+	 *    locate a template file by looking in the following places, in the following order:
146
+	 *        <server path up to>/wp-content/themes/<current active WordPress theme>/
147
+	 *        <assumed full absolute server path>
148
+	 *        <server path up to>/wp-content/uploads/espresso/templates/<current EE theme>/
149
+	 *        <server path up to>/wp-content/uploads/espresso/templates/
150
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/public/<current EE theme>/
151
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/core/templates/<current EE theme>/
152
+	 *        <server path up to>/wp-content/plugins/<EE4 folder>/
153
+	 *    as soon as the template is found in one of these locations, it will be returned or loaded
154
+	 *        Example:
155
+	 *          You are using the WordPress Twenty Sixteen theme,
156
+	 *        and you want to customize the "some-event.template.php" template,
157
+	 *          which is located in the "/relative/path/to/" folder relative to the main EE plugin folder.
158
+	 *          Assuming WP is installed on your server in the "/home/public_html/" folder,
159
+	 *        EEH_Template::locate_template() will look at the following paths in order until the template is found:
160
+	 *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
161
+	 *        /relative/path/to/some-event.template.php
162
+	 *        /home/public_html/wp-content/uploads/espresso/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
163
+	 *        /home/public_html/wp-content/uploads/espresso/templates/relative/path/to/some-event.template.php
164
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/public/Espresso_Arabica_2014/relative/path/to/some-event.template.php
165
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/core/templates/Espresso_Arabica_2014/relative/path/to/some-event.template.php
166
+	 *        /home/public_html/wp-content/plugins/event-espresso-core-reg/relative/path/to/some-event.template.php
167
+	 *          Had you passed an absolute path to your template that was in some other location,
168
+	 *        ie: "/absolute/path/to/some-event.template.php"
169
+	 *          then the search would have been :
170
+	 *        /home/public_html/wp-content/themes/twentysixteen/some-event.template.php
171
+	 *        /absolute/path/to/some-event.template.php
172
+	 *          and stopped there upon finding it in the second location
173
+	 *
174
+	 * @param array|string $templates       array of template file names including extension (or just a single string)
175
+	 * @param array        $template_args   an array of arguments to be extracted for use in the template
176
+	 * @param boolean      $load            whether to pass the located template path on to the
177
+	 *                                      EEH_Template::display_template() method or simply return it
178
+	 * @param boolean      $return_string   whether to send output immediately to screen, or capture and return as a
179
+	 *                                      string
180
+	 * @param boolean      $check_if_custom If TRUE, this flags this method to return boolean for whether this will
181
+	 *                                      generate a custom template or not. Used in places where you don't actually
182
+	 *                                      load the template, you just want to know if there's a custom version of it.
183
+	 * @return string|true
184
+	 * @throws DomainException
185
+	 * @throws InvalidArgumentException
186
+	 * @throws InvalidDataTypeException
187
+	 * @throws InvalidInterfaceException
188
+	 */
189
+	public static function locate_template(
190
+		$templates = [],
191
+		array $template_args = [],
192
+		bool $load = true,
193
+		bool $return_string = true,
194
+		bool $check_if_custom = false
195
+	) {
196
+		$cache_id      = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
197
+		$template_path = TemplateCache::get($cache_id);
198
+		$template_path = $template_path ?: self::resolveTemplatePath($cache_id, (array) $templates, $check_if_custom);
199
+
200
+		if ($check_if_custom && ! empty($template_path)) {
201
+			return true;
202
+		}
203
+
204
+		// if we got it and you want to see it...
205
+		if ($template_path && $load && ! $check_if_custom) {
206
+			if ($return_string) {
207
+				return EEH_Template::display_template($template_path, $template_args, true);
208
+			}
209
+			EEH_Template::display_template($template_path, $template_args);
210
+		}
211
+		return $check_if_custom && ! empty($template_path) ? true : $template_path;
212
+	}
213
+
214
+
215
+	/**
216
+	 * Resolves the path of a template by checking various possible locations.
217
+	 *
218
+	 * This method checks for the existence of a template in several locations,
219
+	 * including the current theme folder, the uploads directory, and the plugin's own template directory.
220
+	 * It uses the provided cache ID to store and retrieve the resolved path from a cache for performance.
221
+	 * If the template is not found in any of the checked locations, an empty string is returned.
222
+	 *
223
+	 * @param string $cache_id        The ID used for caching the resolved path.
224
+	 * @param array  $templates       An array of template file names to search for.
225
+	 * @param bool $check_if_custom   If true, the method will only check if a custom template exists
226
+	 *                                and won't include core plugin folders.
227
+	 * @return string The resolved template path, or an empty string if the template was not found.
228
+	 * @since 5.0.21.p
229
+	 */
230
+	private static function resolveTemplatePath(string $cache_id, array $templates, bool $check_if_custom): string
231
+	{
232
+		// first use WP locate_template to check for template in the current theme folder
233
+		$template_path = $templates ? locate_template($templates) : '';
234
+		// not in the theme
235
+		if (empty($template_path)) {
236
+			// not even a template to look for ?
237
+			if (empty($templates)) {
238
+				$loader = LoaderFactory::getLoader();
239
+				/** @var RequestInterface $request */
240
+				$request = $loader->getShared(RequestInterface::class);
241
+				// get post_type
242
+				$post_type = $request->getRequestParam('post_type');
243
+				/** @var CustomPostTypeDefinitions $custom_post_types */
244
+				$custom_post_types = $loader->getShared(CustomPostTypeDefinitions::class);
245
+				// get array of EE Custom Post Types
246
+				$EE_CPTs = $custom_post_types->getDefinitions();
247
+				// build template name based on request
248
+				if (isset($EE_CPTs[ $post_type ])) {
249
+					$archive_or_single = is_archive() ? 'archive' : '';
250
+					$archive_or_single = is_single() ? 'single' : $archive_or_single;
251
+					$templates[]       = $archive_or_single . '-' . $post_type . '.php';
252
+				}
253
+			}
254
+			// currently active EE template theme
255
+			$current_theme = EE_Config::get_current_theme();
256
+			// array of paths to folders that may contain templates
257
+			$template_folder_paths = [];
258
+
259
+			// add core plugin folders for checking only if we're not $check_if_custom
260
+			if (! $check_if_custom) {
261
+				$core_paths            = [
262
+					// in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
+					EE_PUBLIC . $current_theme,
264
+					// in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
+					EE_TEMPLATES . $current_theme,
266
+					// or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267
+					EE_PLUGIN_DIR_PATH,
268
+				];
269
+				$template_folder_paths = array_merge($template_folder_paths, $core_paths);
270
+			}
271
+
272
+			// now filter that array
273
+			$template_folder_paths = (array) apply_filters(
274
+				'FHEE__EEH_Template__locate_template__template_folder_paths',
275
+				$template_folder_paths
276
+			);
277
+
278
+			// array to hold all possible template paths
279
+			$full_template_paths = [];
280
+			$file_name           = '';
281
+
282
+			// loop through $templates
283
+			foreach ($templates as $template) {
284
+				// normalize directory separators
285
+				$template                      = EEH_File::standardise_directory_separators($template);
286
+				$file_name                     = basename($template);
287
+				$template_path_minus_file_name = substr($template, 0, (strlen($file_name) * -1));
288
+				// while looping through all template folder paths
289
+				foreach ($template_folder_paths as $template_folder_path) {
290
+					// normalize directory separators
291
+					$template_folder_path = EEH_File::standardise_directory_separators($template_folder_path);
292
+					// determine if any common base path exists between the two paths
293
+					$common_base_path = EEH_Template::_find_common_base_path(
294
+						[$template_folder_path, $template_path_minus_file_name]
295
+					);
296
+					if ($common_base_path !== '') {
297
+						// both paths have a common base, so just tack the filename onto our search path
298
+						$resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
299
+					} else {
300
+						// no common base path, so let's just concatenate
301
+						$resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
302
+					}
303
+					// build up our template locations array by adding our resolved paths
304
+					$full_template_paths[] = $resolved_path;
305
+				}
306
+				// if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307
+				array_unshift($full_template_paths, $template);
308
+				// path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
+				array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
310
+			}
311
+			// filter final array of full template paths
312
+			$full_template_paths = apply_filters(
313
+				'FHEE__EEH_Template__locate_template__full_template_paths',
314
+				$full_template_paths,
315
+				$file_name
316
+			);
317
+			// now loop through our final array of template location paths and check each location
318
+			foreach ((array) $full_template_paths as $full_template_path) {
319
+				if (is_readable($full_template_path)) {
320
+					$template_path = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, $full_template_path);
321
+					TemplateCache::set($cache_id, $template_path);
322
+					break;
323
+				}
324
+			}
325
+		}
326
+
327
+		// Display a deprecated notice if the template file is located in the WordPress uploads directory
328
+		if (strpos($template_path, 'wp-content/uploads/espresso') !== false) {
329
+			EE_Error::doing_it_wrong(
330
+				__CLASS__,
331
+				esc_html__(
332
+					'The use of the WordPress uploads directory as a location to override template files has been deprecated.',
333
+					'event_espresso'
334
+				),
335
+				'5.0.0'
336
+			);
337
+		}
338
+
339
+		// hook that can be used to display the full template path that will be used
340
+		do_action('AHEE__EEH_Template__locate_template__full_template_path', $template_path);
341
+
342
+		return $template_path;
343
+	}
344
+
345
+
346
+	/**
347
+	 * _find_common_base_path
348
+	 * given two paths, this determines if there is a common base path between the two
349
+	 *
350
+	 * @param array $paths
351
+	 * @return string
352
+	 */
353
+	protected static function _find_common_base_path($paths)
354
+	{
355
+		$last_offset      = 0;
356
+		$common_base_path = '';
357
+		while (($index = strpos($paths[0], '/', $last_offset)) !== false) {
358
+			$dir_length = $index - $last_offset + 1;
359
+			$directory  = substr($paths[0], $last_offset, $dir_length);
360
+			foreach ($paths as $path) {
361
+				if (substr($path, $last_offset, $dir_length) != $directory) {
362
+					return $common_base_path;
363
+				}
364
+			}
365
+			$common_base_path .= $directory;
366
+			$last_offset      = $index + 1;
367
+		}
368
+		return substr($common_base_path, 0, -1);
369
+	}
370
+
371
+
372
+	/**
373
+	 * load and display a template
374
+	 *
375
+	 * @param bool|string $template_path    server path to the file to be loaded, including file name and extension
376
+	 * @param array       $template_args    an array of arguments to be extracted for use in the template
377
+	 * @param boolean     $return_string    whether to send output immediately to screen, or capture and return as a
378
+	 *                                      string
379
+	 * @param bool        $throw_exceptions if set to true, will throw an exception if the template is either
380
+	 *                                      not found or is not readable
381
+	 * @return string
382
+	 * @throws DomainException
383
+	 */
384
+	public static function display_template(
385
+		$template_path = '',
386
+		$template_args = [],
387
+		$return_string = false,
388
+		$throw_exceptions = false
389
+	) {
390
+		/**
391
+		 * These two filters are intended for last minute changes to templates being loaded and/or template arg
392
+		 * modifications.  NOTE... modifying these things can cause breakage as most templates running through
393
+		 * the display_template method are templates we DON'T want modified (usually because of js
394
+		 * dependencies etc).  So unless you know what you are doing, do NOT filter templates or template args
395
+		 * using this.
396
+		 *
397
+		 * @since 4.6.0
398
+		 */
399
+		$template_path = (string) apply_filters('FHEE__EEH_Template__display_template__template_path', $template_path);
400
+		$template_args = (array) apply_filters('FHEE__EEH_Template__display_template__template_args', $template_args);
401
+
402
+		// you gimme nuttin - YOU GET NUTTIN !!
403
+		if (! $template_path || ! is_readable($template_path)) {
404
+			// ignore whether template is accessible ?
405
+			if ($throw_exceptions) {
406
+				throw new DomainException(
407
+					esc_html__('Invalid, unreadable, or missing file.', 'event_espresso')
408
+				);
409
+			}
410
+			return '';
411
+		}
412
+
413
+		extract($template_args, EXTR_SKIP);
414
+		// because we might want to return a string, we are going to capture the output
415
+		ob_start();
416
+		include($template_path);
417
+		$template = ob_get_clean();
418
+
419
+		if ($return_string) {
420
+			return $template;
421
+		}
422
+		echo wp_kses($template, AllowedTags::getWithFullTags());
423
+		return '';
424
+	}
425
+
426
+
427
+	/**
428
+	 * get_object_css_class - attempts to generate a css class based on the type of EE object passed
429
+	 *
430
+	 * @param EE_Base_Class $object the EE object the css class is being generated for
431
+	 * @param string        $prefix added to the beginning of the generated class
432
+	 * @param string        $suffix added to the end of the generated class
433
+	 * @return string
434
+	 * @throws EE_Error
435
+	 * @throws ReflectionException
436
+	 */
437
+	public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
438
+	{
439
+		// in the beginning...
440
+		$prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
441
+		// da muddle
442
+		$class = '';
443
+		// the end
444
+		$suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
445
+		// is the passed object an EE object ?
446
+		if ($object instanceof EE_Base_Class) {
447
+			// grab the exact type of object
448
+			$obj_class = get_class($object);
449
+			// depending on the type of object...
450
+			// no specifics just yet...
451
+			$class = strtolower(str_replace('_', '-', $obj_class));
452
+			$class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
453
+		}
454
+		return $prefix . $class . $suffix;
455
+	}
456
+
457
+
458
+	/**
459
+	 * EEH_Template::format_currency
460
+	 * This helper takes a raw float value and formats it according to the default config country currency settings, or
461
+	 * the country currency settings from the supplied country ISO code
462
+	 *
463
+	 * @param float   $amount       raw money value
464
+	 * @param boolean $return_raw   whether to return the formatted float value only with no currency sign or code
465
+	 * @param boolean $display_code whether to display the country code (USD). Default = TRUE
466
+	 * @param string  $CNT_ISO      2-letter ISO code for a country
467
+	 * @param string  $cur_code_span_class
468
+	 * @return string        the html output for the formatted money value
469
+	 */
470
+	public static function format_currency(
471
+		$amount = null,
472
+		$return_raw = false,
473
+		$display_code = true,
474
+		$CNT_ISO = '',
475
+		$cur_code_span_class = 'currency-code'
476
+	) {
477
+		// ensure amount was received
478
+		if ($amount === null) {
479
+			$msg = esc_html__('In order to format currency, an amount needs to be passed.', 'event_espresso');
480
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
481
+			return '';
482
+		}
483
+		// ensure amount is float
484
+		$amount  = (float) apply_filters('FHEE__EEH_Template__format_currency__raw_amount', (float) $amount);
485
+		$CNT_ISO = apply_filters('FHEE__EEH_Template__format_currency__CNT_ISO', $CNT_ISO, $amount);
486
+		// filter raw amount (allows 0.00 to be changed to "free" for example)
487
+		$amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
488
+		// still a number, or was amount converted to a string like "free" ?
489
+		if (! is_float($amount_formatted)) {
490
+			return esc_html($amount_formatted);
491
+		}
492
+		try {
493
+			// was a country ISO code passed ? if so generate currency config object for that country
494
+			$mny = $CNT_ISO !== '' ? new EE_Currency_Config($CNT_ISO) : null;
495
+		} catch (Exception $e) {
496
+			// eat exception
497
+			$mny = null;
498
+		}
499
+		// verify results
500
+		if (! $mny instanceof EE_Currency_Config) {
501
+			// set default config country currency settings
502
+			$mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
503
+				? EE_Registry::instance()->CFG->currency
504
+				: new EE_Currency_Config();
505
+		}
506
+		// format float
507
+		$amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
508
+		// add formatting ?
509
+		if (! $return_raw) {
510
+			// add currency sign
511
+			if ($mny->sign_b4) {
512
+				if ($amount >= 0) {
513
+					$amount_formatted = $mny->sign . $amount_formatted;
514
+				} else {
515
+					$amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
516
+				}
517
+			} else {
518
+				$amount_formatted = $amount_formatted . $mny->sign;
519
+			}
520
+
521
+			// filter to allow global setting of display_code
522
+			$display_code = (bool) apply_filters(
523
+				'FHEE__EEH_Template__format_currency__display_code',
524
+				$display_code
525
+			);
526
+
527
+			// add currency code ?
528
+			$amount_formatted = $display_code
529
+				? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
530
+				: $amount_formatted;
531
+		}
532
+		// filter results
533
+		$amount_formatted = apply_filters(
534
+			'FHEE__EEH_Template__format_currency__amount_formatted',
535
+			$amount_formatted,
536
+			$mny,
537
+			$return_raw
538
+		);
539
+		// clean up vars
540
+		unset($mny);
541
+		// return formatted currency amount
542
+		return $amount_formatted;
543
+	}
544
+
545
+
546
+	/**
547
+	 * This function is used for outputting the localized label for a given status id in the schema requested (and
548
+	 * possibly plural).  The intended use of this function is only for cases where wanting a label outside of a
549
+	 * related status model or model object (i.e. in documentation etc.)
550
+	 *
551
+	 * @param string  $status_id  Status ID matching a registered status in the esp_status table.  If there is no
552
+	 *                            match, then 'Unknown' will be returned.
553
+	 * @param boolean $plural     Whether to return plural or not
554
+	 * @param string  $schema     'UPPER', 'lower', or 'Sentence'
555
+	 * @return string             The localized label for the status id.
556
+	 * @throws EE_Error
557
+	 */
558
+	public static function pretty_status($status_id, $plural = false, $schema = 'upper')
559
+	{
560
+		$status = EEM_Status::instance()->localized_status(
561
+			[$status_id => esc_html__('unknown', 'event_espresso')],
562
+			$plural,
563
+			$schema
564
+		);
565
+		return $status[ $status_id ];
566
+	}
567
+
568
+
569
+	/**
570
+	 * This helper just returns a button or link for the given parameters
571
+	 *
572
+	 * @param string $url   the url for the link, note that `esc_url` will be called on it
573
+	 * @param string $label What is the label you want displayed for the button
574
+	 * @param string $class what class is used for the button (defaults to 'button--primary')
575
+	 * @param string $icon
576
+	 * @param string $title
577
+	 * @return string the html output for the button
578
+	 */
579
+	public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
580
+	{
581
+		$icon_html = '';
582
+		if (! empty($icon)) {
583
+			$dashicons = preg_split("(ee-icon |dashicons )", $icon);
584
+			$dashicons = array_filter($dashicons);
585
+			$count     = count($dashicons);
586
+			$icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
587
+			foreach ($dashicons as $dashicon) {
588
+				$type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
589
+				$icon_html .= '<span class="' . $type . $dashicon . '"></span>';
590
+			}
591
+			$icon_html .= $count > 1 ? '</span>' : '';
592
+		}
593
+		// sanitize & escape
594
+		$id    = sanitize_title_with_dashes($label);
595
+		$url   = esc_url_raw($url);
596
+		$class = esc_attr($class);
597
+		$title = esc_attr($title);
598
+		$class .= $title ? ' ee-aria-tooltip' : '';
599
+		$title = $title ? " aria-label='{$title}'" : '';
600
+		$label = esc_html($label);
601
+		return "<a id='{$id}' href='{$url}' class='{$class}'{$title}>{$icon_html}{$label}</a>";
602
+	}
603
+
604
+
605
+	/**
606
+	 * This returns a generated link that will load the related help tab on admin pages.
607
+	 *
608
+	 * @param string      $help_tab_id the id for the connected help tab
609
+	 * @param bool|string $page        The page identifier for the page the help tab is on
610
+	 * @param bool|string $action      The action (route) for the admin page the help tab is on.
611
+	 * @param bool|string $icon_style  (optional) include css class for the style you want to use for the help icon.
612
+	 * @param bool|string $help_text   (optional) send help text you want to use for the link if default not to be used
613
+	 * @return string              generated link
614
+	 */
615
+	public static function get_help_tab_link(
616
+		$help_tab_id,
617
+		$page = false,
618
+		$action = false,
619
+		$icon_style = false,
620
+		$help_text = false
621
+	) {
622
+		/** @var RequestInterface $request */
623
+		$request = LoaderFactory::getLoader()->getShared(RequestInterface::class);
624
+		$page    = $page ?: $request->getRequestParam('page', '', 'key');
625
+		$action  = $action ?: $request->getRequestParam('action', 'default', 'key');
626
+
627
+
628
+		$help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
629
+		$icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
630
+		$help_text    = ! $help_text ? '' : $help_text;
631
+		return '
632 632
             <a id="' . esc_attr($help_tab_lnk) . '"
633 633
                class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon) . '"
634 634
                aria-label="' . esc_attr__(
635
-                   'Click to open the \'Help\' tab for more information about this feature.',
636
-                   'event_espresso'
637
-               ) . '"
635
+				   'Click to open the \'Help\' tab for more information about this feature.',
636
+				   'event_espresso'
637
+			   ) . '"
638 638
             >
639 639
                 ' . wp_kses($help_text, AllowedTags::getAllowedTags()) . '
640 640
             </a>';
641
-    }
642
-
643
-
644
-    /**
645
-     * This is a helper method to generate a status legend for a given status array.
646
-     * Note this will only work if the incoming statuses have a key in the EEM_Status->localized_status() methods
647
-     * status_array.
648
-     *
649
-     * @param array  $status_array   array of statuses that will make up the legend. In format:
650
-     *                               array(
651
-     *                               'status_item' => 'status_name'
652
-     *                               )
653
-     * @param string $active_status  This is used to indicate what the active status is IF that is to be highlighted in
654
-     *                               the legend.
655
-     * @return string               html structure for status.
656
-     * @throws EE_Error
657
-     */
658
-    public static function status_legend($status_array, $active_status = '')
659
-    {
660
-        if (! is_array($status_array)) {
661
-            throw new EE_Error(
662
-                esc_html__(
663
-                    'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
664
-                    'event_espresso'
665
-                )
666
-            );
667
-        }
668
-
669
-        $content = '
641
+	}
642
+
643
+
644
+	/**
645
+	 * This is a helper method to generate a status legend for a given status array.
646
+	 * Note this will only work if the incoming statuses have a key in the EEM_Status->localized_status() methods
647
+	 * status_array.
648
+	 *
649
+	 * @param array  $status_array   array of statuses that will make up the legend. In format:
650
+	 *                               array(
651
+	 *                               'status_item' => 'status_name'
652
+	 *                               )
653
+	 * @param string $active_status  This is used to indicate what the active status is IF that is to be highlighted in
654
+	 *                               the legend.
655
+	 * @return string               html structure for status.
656
+	 * @throws EE_Error
657
+	 */
658
+	public static function status_legend($status_array, $active_status = '')
659
+	{
660
+		if (! is_array($status_array)) {
661
+			throw new EE_Error(
662
+				esc_html__(
663
+					'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
664
+					'event_espresso'
665
+				)
666
+			);
667
+		}
668
+
669
+		$content = '
670 670
             <div class="ee-list-table-legend-container">
671 671
                 <h4 class="status-legend-title">
672 672
                     ' . esc_html__('Status Legend', 'event_espresso') . '
673 673
                 </h4>
674 674
                 <dl class="ee-list-table-legend">';
675 675
 
676
-        foreach ($status_array as $item => $status) {
677
-            $active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
678
-            $content      .= '
676
+		foreach ($status_array as $item => $status) {
677
+			$active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
678
+			$content      .= '
679 679
                     <dt id="' . esc_attr('ee-legend-item-tooltip-' . $item) . '" ' . $active_class . '>
680 680
                         <span class="' . esc_attr('ee-status-legend ee-status-bg--' . $status) . '"></span>
681 681
                         <span class="ee-legend-description">
682 682
                             ' . EEH_Template::pretty_status($status, false, 'sentence') . '
683 683
                         </span>
684 684
                     </dt>';
685
-        }
685
+		}
686 686
 
687
-        $content .= '
687
+		$content .= '
688 688
                 </dl>
689 689
             </div>
690 690
 ';
691
-        return $content;
692
-    }
693
-
694
-
695
-    /**
696
-     * Gets HTML for laying out a deeply-nested array (and objects) in a format
697
-     * that's nice for presenting in the wp admin
698
-     *
699
-     * @param mixed $data
700
-     * @return string
701
-     */
702
-    public static function layout_array_as_table($data)
703
-    {
704
-        if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
705
-            $data = (array) $data;
706
-        }
707
-        ob_start();
708
-        if (is_array($data)) {
709
-            if (EEH_Array::is_associative_array($data)) { ?>
691
+		return $content;
692
+	}
693
+
694
+
695
+	/**
696
+	 * Gets HTML for laying out a deeply-nested array (and objects) in a format
697
+	 * that's nice for presenting in the wp admin
698
+	 *
699
+	 * @param mixed $data
700
+	 * @return string
701
+	 */
702
+	public static function layout_array_as_table($data)
703
+	{
704
+		if (is_object($data) || $data instanceof __PHP_Incomplete_Class) {
705
+			$data = (array) $data;
706
+		}
707
+		ob_start();
708
+		if (is_array($data)) {
709
+			if (EEH_Array::is_associative_array($data)) { ?>
710 710
                 <table class="widefat">
711 711
                     <tbody>
712 712
                         <?php foreach ($data as $data_key => $data_values) { ?>
@@ -724,304 +724,304 @@  discard block
 block discarded – undo
724 724
             <?php } else { ?>
725 725
                 <ul>
726 726
                     <?php
727
-                    foreach ($data as $datum) {
728
-                        echo "<li>";
729
-                        echo self::layout_array_as_table($datum);
730
-                        echo "</li>";
731
-                    } ?>
727
+					foreach ($data as $datum) {
728
+						echo "<li>";
729
+						echo self::layout_array_as_table($datum);
730
+						echo "</li>";
731
+					} ?>
732 732
                 </ul>
733 733
             <?php }
734
-        } else {
735
-            // simple value
736
-            echo esc_html($data);
737
-        }
738
-        return ob_get_clean();
739
-    }
740
-
741
-
742
-    /**
743
-     * wrapper for self::get_paging_html() that simply echos the generated paging html
744
-     *
745
-     * @param        $total_items
746
-     * @param        $current
747
-     * @param        $per_page
748
-     * @param        $url
749
-     * @param bool   $show_num_field
750
-     * @param string $paged_arg_name
751
-     * @param array  $items_label
752
-     * @see   self:get_paging_html() for argument docs.
753
-     * @since 4.4.0
754
-     */
755
-    public static function paging_html(
756
-        $total_items,
757
-        $current,
758
-        $per_page,
759
-        $url,
760
-        $show_num_field = true,
761
-        $paged_arg_name = 'paged',
762
-        $items_label = []
763
-    ) {
764
-        echo self::get_paging_html(
765
-            $total_items,
766
-            $current,
767
-            $per_page,
768
-            $url,
769
-            $show_num_field,
770
-            $paged_arg_name,
771
-            $items_label
772
-        );
773
-    }
774
-
775
-
776
-    /**
777
-     * A method for generating paging similar to WP_List_Table
778
-     *
779
-     * @param int    $total_items       How many total items there are to page.
780
-     * @param int    $current           What the current page is.
781
-     * @param int    $per_page          How many items per page.
782
-     * @param string $url               What the base url for page links is.
783
-     * @param bool   $show_num_field    Whether to show the input for changing page number.
784
-     * @param string $paged_arg_name    The name of the key for the paged query argument.
785
-     * @param array  $items_label       An array of singular/plural values for the items label:
786
-     *                                  array(
787
-     *                                  'single' => 'item',
788
-     *                                  'plural' => 'items'
789
-     *                                  )
790
-     * @return  string
791
-     * @since    4.4.0
792
-     * @see      wp-admin/includes/class-wp-list-table.php WP_List_Table::pagination()
793
-     */
794
-    public static function get_paging_html(
795
-        int $total_items,
796
-        int $current,
797
-        int $per_page,
798
-        string $url,
799
-        bool $show_num_field = true,
800
-        string $paged_arg_name = 'paged',
801
-        array $items_label = [],
802
-        string $button_size = 'small'
803
-    ): string {
804
-        $page_links     = [];
805
-        $paged_arg_name = empty($paged_arg_name) ? 'paged' : sanitize_key($paged_arg_name);
806
-
807
-        // filter items_label
808
-        $items_label = apply_filters(
809
-            'FHEE__EEH_Template__get_paging_html__items_label',
810
-            $items_label
811
-        );
812
-
813
-        if (
814
-            empty($items_label)
815
-            || ! is_array($items_label)
816
-            || ! isset($items_label['single'])
817
-            || ! isset($items_label['plural'])
818
-        ) {
819
-            $items_label = [
820
-                'single' => esc_html__('1 item', 'event_espresso'),
821
-                'plural' => esc_html__('%s items', 'event_espresso'),
822
-            ];
823
-        } else {
824
-            $items_label = [
825
-                'single' => '1 ' . esc_html($items_label['single']),
826
-                'plural' => '%s ' . esc_html($items_label['plural']),
827
-            ];
828
-        }
829
-
830
-        $total_pages = (int) ceil($total_items / $per_page);
831
-
832
-        if ($total_pages <= 1) {
833
-            return '';
834
-        }
835
-
836
-        $item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
837
-
838
-        $output = '<span class="displaying-num">' . $item_label . '</span>';
839
-
840
-        $disable_first = $current === 1 ? 'disabled' : '';
841
-        $disable_last  = $current === $total_pages ? 'disabled' : '';
842
-
843
-        $button_size    = in_array($button_size, ['tiny', 'small', 'default', 'big']) ? $button_size : 'small';
844
-        $button_classes = "button button--secondary button--icon-only button--$button_size";
845
-
846
-        $page_links[] = sprintf(
847
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
848
-            esc_attr("first-page $button_classes $disable_first"),
849
-            esc_attr__('Go to the first page', 'event_espresso'),
850
-            esc_url_raw(remove_query_arg($paged_arg_name, $url)),
851
-            '&laquo;'
852
-        );
853
-
854
-        $page_links[] = sprintf(
855
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
856
-            esc_attr("prev-page $button_classes $disable_first"),
857
-            esc_attr__('Go to the previous page', 'event_espresso'),
858
-            esc_url_raw(add_query_arg($paged_arg_name, max(1, $current - 1), $url)),
859
-            '&lsaquo;'
860
-        );
861
-
862
-        $html_current_page = $show_num_field
863
-            ? sprintf(
864
-                "<input class='current-page ee-input-size--small' title='%s' type='text' name=$paged_arg_name value='%s' size='%d' />",
865
-                esc_attr__('Current page', 'event_espresso'),
866
-                esc_attr($current),
867
-                strlen($total_pages)
868
-            )
869
-            : $current;
870
-
871
-        $html_total_pages = sprintf(
872
-            '<span class="total-pages">%s</span>',
873
-            number_format_i18n($total_pages)
874
-        );
875
-        $page_links[]     = sprintf(
876
-            _x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
877
-            "{$html_current_page}<span class='paging-input-of'>",
878
-            "</span>{$html_total_pages}",
879
-            '<span class="paging-input">',
880
-            '</span>'
881
-        );
882
-
883
-        $page_links[] = sprintf(
884
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
885
-            esc_attr("next-page $button_classes $disable_last"),
886
-            esc_attr__('Go to the next page', 'event_espresso'),
887
-            esc_url_raw(add_query_arg($paged_arg_name, min($total_pages, $current + 1), $url)),
888
-            '&rsaquo;'
889
-        );
890
-
891
-        $page_links[] = sprintf(
892
-            '<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
893
-            esc_attr("last-page $button_classes $disable_last"),
894
-            esc_attr__('Go to the last page', 'event_espresso'),
895
-            esc_url_raw(add_query_arg($paged_arg_name, $total_pages, $url)),
896
-            '&raquo;'
897
-        );
898
-
899
-        $output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
900
-
901
-        $page_class = ' no-pages';
902
-        if ($total_pages) {
903
-            $page_class = $total_pages < 2 ? ' one-page' : '';
904
-        }
905
-
906
-        return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
907
-    }
908
-
909
-
910
-    /**
911
-     * @param string $wrap_class
912
-     * @param string $wrap_id
913
-     * @param array  $query_args
914
-     * @return string
915
-     */
916
-    public static function powered_by_event_espresso(
917
-        string $wrap_class = '',
918
-        string $wrap_id = '',
919
-        array $query_args = []
920
-    ): string {
921
-        $request = LoaderFactory::getShared(RequestInterface::class);
922
-        if (
923
-            $request->isActivation()
924
-            || strpos($request->requestUri(true), 'wp-admin/update.php') !== false
925
-        ) {
926
-            return '';
927
-        }
928
-        $cache_id = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
929
-        $cache    = TemplateCache::get($cache_id);
930
-        if ($cache) {
931
-            return $cache;
932
-        }
933
-
934
-        $admin = is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX);
935
-        if (
936
-            ! $admin
937
-            && ! apply_filters(
938
-                'FHEE__EEH_Template__powered_by_event_espresso__show_reg_footer',
939
-                EE_Registry::instance()->CFG->admin->show_reg_footer
940
-            )
941
-        ) {
942
-            return '';
943
-        }
944
-        $tag        = $admin ? 'span' : 'div';
945
-        $attributes = ! empty($wrap_id) ? " id=\"{$wrap_id}\"" : '';
946
-        $wrap_class = $admin ? "{$wrap_class} float-left" : $wrap_class;
947
-        $attributes .= ! empty($wrap_class)
948
-            ? " class=\"{$wrap_class} powered-by-event-espresso-credit\""
949
-            : ' class="powered-by-event-espresso-credit"';
950
-        $query_args = array_merge(
951
-            [
952
-                'ap_id'        => EE_Registry::instance()->CFG->admin->affiliate_id(),
953
-                'utm_source'   => 'powered_by_event_espresso',
954
-                'utm_medium'   => 'link',
955
-                'utm_campaign' => 'powered_by',
956
-            ],
957
-            $query_args
958
-        );
959
-        $powered_by = apply_filters(
960
-            'FHEE__EEH_Template__powered_by_event_espresso_text',
961
-            $admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
962
-        );
963
-        $url        = add_query_arg($query_args, 'https://eventespresso.com/');
964
-        $url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
965
-        $template   = (string) apply_filters(
966
-            'FHEE__EEH_Template__powered_by_event_espresso__html',
967
-            sprintf(
968
-                esc_html_x(
969
-                    '%3$s%1$sOnline event registration and ticketing powered by %2$s%3$s',
970
-                    'Online event registration and ticketing powered by [link to eventespresso.com]',
971
-                    'event_espresso'
972
-                ),
973
-                "<$tag$attributes>",
974
-                "<a href=\"$url\" target=\"_blank\" rel=\"nofollow\">$powered_by</a></$tag>",
975
-                $admin ? '' : '<br />'
976
-            ),
977
-            $wrap_class,
978
-            $wrap_id
979
-        );
980
-        TemplateCache::set($cache_id, $template);
981
-        return $template;
982
-    }
983
-
984
-
985
-    /**
986
-     * @param string $image_name
987
-     * @return string|null
988
-     * @since   4.10.14.p
989
-     */
990
-    public static function getScreenshotUrl($image_name)
991
-    {
992
-        return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
993
-    }
734
+		} else {
735
+			// simple value
736
+			echo esc_html($data);
737
+		}
738
+		return ob_get_clean();
739
+	}
740
+
741
+
742
+	/**
743
+	 * wrapper for self::get_paging_html() that simply echos the generated paging html
744
+	 *
745
+	 * @param        $total_items
746
+	 * @param        $current
747
+	 * @param        $per_page
748
+	 * @param        $url
749
+	 * @param bool   $show_num_field
750
+	 * @param string $paged_arg_name
751
+	 * @param array  $items_label
752
+	 * @see   self:get_paging_html() for argument docs.
753
+	 * @since 4.4.0
754
+	 */
755
+	public static function paging_html(
756
+		$total_items,
757
+		$current,
758
+		$per_page,
759
+		$url,
760
+		$show_num_field = true,
761
+		$paged_arg_name = 'paged',
762
+		$items_label = []
763
+	) {
764
+		echo self::get_paging_html(
765
+			$total_items,
766
+			$current,
767
+			$per_page,
768
+			$url,
769
+			$show_num_field,
770
+			$paged_arg_name,
771
+			$items_label
772
+		);
773
+	}
774
+
775
+
776
+	/**
777
+	 * A method for generating paging similar to WP_List_Table
778
+	 *
779
+	 * @param int    $total_items       How many total items there are to page.
780
+	 * @param int    $current           What the current page is.
781
+	 * @param int    $per_page          How many items per page.
782
+	 * @param string $url               What the base url for page links is.
783
+	 * @param bool   $show_num_field    Whether to show the input for changing page number.
784
+	 * @param string $paged_arg_name    The name of the key for the paged query argument.
785
+	 * @param array  $items_label       An array of singular/plural values for the items label:
786
+	 *                                  array(
787
+	 *                                  'single' => 'item',
788
+	 *                                  'plural' => 'items'
789
+	 *                                  )
790
+	 * @return  string
791
+	 * @since    4.4.0
792
+	 * @see      wp-admin/includes/class-wp-list-table.php WP_List_Table::pagination()
793
+	 */
794
+	public static function get_paging_html(
795
+		int $total_items,
796
+		int $current,
797
+		int $per_page,
798
+		string $url,
799
+		bool $show_num_field = true,
800
+		string $paged_arg_name = 'paged',
801
+		array $items_label = [],
802
+		string $button_size = 'small'
803
+	): string {
804
+		$page_links     = [];
805
+		$paged_arg_name = empty($paged_arg_name) ? 'paged' : sanitize_key($paged_arg_name);
806
+
807
+		// filter items_label
808
+		$items_label = apply_filters(
809
+			'FHEE__EEH_Template__get_paging_html__items_label',
810
+			$items_label
811
+		);
812
+
813
+		if (
814
+			empty($items_label)
815
+			|| ! is_array($items_label)
816
+			|| ! isset($items_label['single'])
817
+			|| ! isset($items_label['plural'])
818
+		) {
819
+			$items_label = [
820
+				'single' => esc_html__('1 item', 'event_espresso'),
821
+				'plural' => esc_html__('%s items', 'event_espresso'),
822
+			];
823
+		} else {
824
+			$items_label = [
825
+				'single' => '1 ' . esc_html($items_label['single']),
826
+				'plural' => '%s ' . esc_html($items_label['plural']),
827
+			];
828
+		}
829
+
830
+		$total_pages = (int) ceil($total_items / $per_page);
831
+
832
+		if ($total_pages <= 1) {
833
+			return '';
834
+		}
835
+
836
+		$item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
837
+
838
+		$output = '<span class="displaying-num">' . $item_label . '</span>';
839
+
840
+		$disable_first = $current === 1 ? 'disabled' : '';
841
+		$disable_last  = $current === $total_pages ? 'disabled' : '';
842
+
843
+		$button_size    = in_array($button_size, ['tiny', 'small', 'default', 'big']) ? $button_size : 'small';
844
+		$button_classes = "button button--secondary button--icon-only button--$button_size";
845
+
846
+		$page_links[] = sprintf(
847
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
848
+			esc_attr("first-page $button_classes $disable_first"),
849
+			esc_attr__('Go to the first page', 'event_espresso'),
850
+			esc_url_raw(remove_query_arg($paged_arg_name, $url)),
851
+			'&laquo;'
852
+		);
853
+
854
+		$page_links[] = sprintf(
855
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
856
+			esc_attr("prev-page $button_classes $disable_first"),
857
+			esc_attr__('Go to the previous page', 'event_espresso'),
858
+			esc_url_raw(add_query_arg($paged_arg_name, max(1, $current - 1), $url)),
859
+			'&lsaquo;'
860
+		);
861
+
862
+		$html_current_page = $show_num_field
863
+			? sprintf(
864
+				"<input class='current-page ee-input-size--small' title='%s' type='text' name=$paged_arg_name value='%s' size='%d' />",
865
+				esc_attr__('Current page', 'event_espresso'),
866
+				esc_attr($current),
867
+				strlen($total_pages)
868
+			)
869
+			: $current;
870
+
871
+		$html_total_pages = sprintf(
872
+			'<span class="total-pages">%s</span>',
873
+			number_format_i18n($total_pages)
874
+		);
875
+		$page_links[]     = sprintf(
876
+			_x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
877
+			"{$html_current_page}<span class='paging-input-of'>",
878
+			"</span>{$html_total_pages}",
879
+			'<span class="paging-input">',
880
+			'</span>'
881
+		);
882
+
883
+		$page_links[] = sprintf(
884
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
885
+			esc_attr("next-page $button_classes $disable_last"),
886
+			esc_attr__('Go to the next page', 'event_espresso'),
887
+			esc_url_raw(add_query_arg($paged_arg_name, min($total_pages, $current + 1), $url)),
888
+			'&rsaquo;'
889
+		);
890
+
891
+		$page_links[] = sprintf(
892
+			'<a class="%s" aria-label="%s" href="%s"><span class="ee-pagination-arrow">%s</span></a>',
893
+			esc_attr("last-page $button_classes $disable_last"),
894
+			esc_attr__('Go to the last page', 'event_espresso'),
895
+			esc_url_raw(add_query_arg($paged_arg_name, $total_pages, $url)),
896
+			'&raquo;'
897
+		);
898
+
899
+		$output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
900
+
901
+		$page_class = ' no-pages';
902
+		if ($total_pages) {
903
+			$page_class = $total_pages < 2 ? ' one-page' : '';
904
+		}
905
+
906
+		return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
907
+	}
908
+
909
+
910
+	/**
911
+	 * @param string $wrap_class
912
+	 * @param string $wrap_id
913
+	 * @param array  $query_args
914
+	 * @return string
915
+	 */
916
+	public static function powered_by_event_espresso(
917
+		string $wrap_class = '',
918
+		string $wrap_id = '',
919
+		array $query_args = []
920
+	): string {
921
+		$request = LoaderFactory::getShared(RequestInterface::class);
922
+		if (
923
+			$request->isActivation()
924
+			|| strpos($request->requestUri(true), 'wp-admin/update.php') !== false
925
+		) {
926
+			return '';
927
+		}
928
+		$cache_id = TemplateCache::generateCacheID(__FUNCTION__, func_get_args());
929
+		$cache    = TemplateCache::get($cache_id);
930
+		if ($cache) {
931
+			return $cache;
932
+		}
933
+
934
+		$admin = is_admin() && ! (defined('DOING_AJAX') && DOING_AJAX);
935
+		if (
936
+			! $admin
937
+			&& ! apply_filters(
938
+				'FHEE__EEH_Template__powered_by_event_espresso__show_reg_footer',
939
+				EE_Registry::instance()->CFG->admin->show_reg_footer
940
+			)
941
+		) {
942
+			return '';
943
+		}
944
+		$tag        = $admin ? 'span' : 'div';
945
+		$attributes = ! empty($wrap_id) ? " id=\"{$wrap_id}\"" : '';
946
+		$wrap_class = $admin ? "{$wrap_class} float-left" : $wrap_class;
947
+		$attributes .= ! empty($wrap_class)
948
+			? " class=\"{$wrap_class} powered-by-event-espresso-credit\""
949
+			: ' class="powered-by-event-espresso-credit"';
950
+		$query_args = array_merge(
951
+			[
952
+				'ap_id'        => EE_Registry::instance()->CFG->admin->affiliate_id(),
953
+				'utm_source'   => 'powered_by_event_espresso',
954
+				'utm_medium'   => 'link',
955
+				'utm_campaign' => 'powered_by',
956
+			],
957
+			$query_args
958
+		);
959
+		$powered_by = apply_filters(
960
+			'FHEE__EEH_Template__powered_by_event_espresso_text',
961
+			$admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
962
+		);
963
+		$url        = add_query_arg($query_args, 'https://eventespresso.com/');
964
+		$url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
965
+		$template   = (string) apply_filters(
966
+			'FHEE__EEH_Template__powered_by_event_espresso__html',
967
+			sprintf(
968
+				esc_html_x(
969
+					'%3$s%1$sOnline event registration and ticketing powered by %2$s%3$s',
970
+					'Online event registration and ticketing powered by [link to eventespresso.com]',
971
+					'event_espresso'
972
+				),
973
+				"<$tag$attributes>",
974
+				"<a href=\"$url\" target=\"_blank\" rel=\"nofollow\">$powered_by</a></$tag>",
975
+				$admin ? '' : '<br />'
976
+			),
977
+			$wrap_class,
978
+			$wrap_id
979
+		);
980
+		TemplateCache::set($cache_id, $template);
981
+		return $template;
982
+	}
983
+
984
+
985
+	/**
986
+	 * @param string $image_name
987
+	 * @return string|null
988
+	 * @since   4.10.14.p
989
+	 */
990
+	public static function getScreenshotUrl($image_name)
991
+	{
992
+		return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
993
+	}
994 994
 }
995 995
 
996 996
 
997 997
 if (! function_exists('espresso_pagination')) {
998
-    /**
999
-     *    espresso_pagination
1000
-     *
1001
-     * @access    public
1002
-     * @return    void
1003
-     */
1004
-    function espresso_pagination()
1005
-    {
1006
-        global $wp_query;
1007
-        $big        = 999999999; // need an unlikely integer
1008
-        $pagination = paginate_links(
1009
-            [
1010
-                'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
1011
-                'format'       => '?paged=%#%',
1012
-                'current'      => max(1, get_query_var('paged')),
1013
-                'total'        => $wp_query->max_num_pages,
1014
-                'show_all'     => true,
1015
-                'end_size'     => 10,
1016
-                'mid_size'     => 6,
1017
-                'prev_next'    => true,
1018
-                'prev_text'    => esc_html__('&lsaquo; PREV', 'event_espresso'),
1019
-                'next_text'    => esc_html__('NEXT &rsaquo;', 'event_espresso'),
1020
-                'type'         => 'plain',
1021
-                'add_args'     => false,
1022
-                'add_fragment' => '',
1023
-            ]
1024
-        );
1025
-        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1026
-    }
998
+	/**
999
+	 *    espresso_pagination
1000
+	 *
1001
+	 * @access    public
1002
+	 * @return    void
1003
+	 */
1004
+	function espresso_pagination()
1005
+	{
1006
+		global $wp_query;
1007
+		$big        = 999999999; // need an unlikely integer
1008
+		$pagination = paginate_links(
1009
+			[
1010
+				'base'         => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
1011
+				'format'       => '?paged=%#%',
1012
+				'current'      => max(1, get_query_var('paged')),
1013
+				'total'        => $wp_query->max_num_pages,
1014
+				'show_all'     => true,
1015
+				'end_size'     => 10,
1016
+				'mid_size'     => 6,
1017
+				'prev_next'    => true,
1018
+				'prev_text'    => esc_html__('&lsaquo; PREV', 'event_espresso'),
1019
+				'next_text'    => esc_html__('NEXT &rsaquo;', 'event_espresso'),
1020
+				'type'         => 'plain',
1021
+				'add_args'     => false,
1022
+				'add_fragment' => '',
1023
+			]
1024
+		);
1025
+		echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1026
+	}
1027 1027
 }
Please login to merge, or discard this patch.
Spacing   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -8,7 +8,7 @@  discard block
 block discarded – undo
8 8
 use EventEspresso\core\services\request\RequestInterface;
9 9
 use EventEspresso\core\services\request\sanitizers\AllowedTags;
10 10
 
11
-if (! function_exists('espresso_get_template_part')) {
11
+if ( ! function_exists('espresso_get_template_part')) {
12 12
     /**
13 13
      * espresso_get_template_part
14 14
      * basically a copy of the WordPress get_template_part() function but uses EEH_Template::locate_template() instead, and doesn't add base versions of files
@@ -24,7 +24,7 @@  discard block
 block discarded – undo
24 24
 }
25 25
 
26 26
 
27
-if (! function_exists('espresso_get_object_css_class')) {
27
+if ( ! function_exists('espresso_get_object_css_class')) {
28 28
     /**
29 29
      * espresso_get_object_css_class - attempts to generate a css class based on the type of EE object passed
30 30
      *
@@ -74,9 +74,9 @@  discard block
 block discarded – undo
74 74
      */
75 75
     public static function load_espresso_theme_functions()
76 76
     {
77
-        if (! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
-            if (is_readable(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php')) {
79
-                require_once(EE_PUBLIC . EE_Config::get_current_theme() . '/functions.php');
77
+        if ( ! defined('EE_THEME_FUNCTIONS_LOADED')) {
78
+            if (is_readable(EE_PUBLIC.EE_Config::get_current_theme().'/functions.php')) {
79
+                require_once(EE_PUBLIC.EE_Config::get_current_theme().'/functions.php');
80 80
             }
81 81
         }
82 82
     }
@@ -90,16 +90,16 @@  discard block
 block discarded – undo
90 90
     public static function get_espresso_themes(): array
91 91
     {
92 92
         if (empty(EEH_Template::$_espresso_themes)) {
93
-            $espresso_themes = glob(EE_PUBLIC . '*', GLOB_ONLYDIR);
93
+            $espresso_themes = glob(EE_PUBLIC.'*', GLOB_ONLYDIR);
94 94
             if (empty($espresso_themes)) {
95 95
                 return [];
96 96
             }
97 97
             if (($key = array_search('global_assets', $espresso_themes)) !== false) {
98
-                unset($espresso_themes[ $key ]);
98
+                unset($espresso_themes[$key]);
99 99
             }
100 100
             EEH_Template::$_espresso_themes = [];
101 101
             foreach ($espresso_themes as $espresso_theme) {
102
-                EEH_Template::$_espresso_themes[ basename($espresso_theme) ] = $espresso_theme;
102
+                EEH_Template::$_espresso_themes[basename($espresso_theme)] = $espresso_theme;
103 103
             }
104 104
         }
105 105
         return EEH_Template::$_espresso_themes;
@@ -126,7 +126,7 @@  discard block
 block discarded – undo
126 126
     ) {
127 127
         do_action("get_template_part_$slug-$name", $slug, $name);
128 128
         $template = $slug;
129
-        $name      = (string) $name;
129
+        $name = (string) $name;
130 130
         if ($name != '') {
131 131
             $template .= "-$name";
132 132
         }
@@ -245,10 +245,10 @@  discard block
 block discarded – undo
245 245
                 // get array of EE Custom Post Types
246 246
                 $EE_CPTs = $custom_post_types->getDefinitions();
247 247
                 // build template name based on request
248
-                if (isset($EE_CPTs[ $post_type ])) {
248
+                if (isset($EE_CPTs[$post_type])) {
249 249
                     $archive_or_single = is_archive() ? 'archive' : '';
250 250
                     $archive_or_single = is_single() ? 'single' : $archive_or_single;
251
-                    $templates[]       = $archive_or_single . '-' . $post_type . '.php';
251
+                    $templates[]       = $archive_or_single.'-'.$post_type.'.php';
252 252
                 }
253 253
             }
254 254
             // currently active EE template theme
@@ -257,12 +257,12 @@  discard block
 block discarded – undo
257 257
             $template_folder_paths = [];
258 258
 
259 259
             // add core plugin folders for checking only if we're not $check_if_custom
260
-            if (! $check_if_custom) {
261
-                $core_paths            = [
260
+            if ( ! $check_if_custom) {
261
+                $core_paths = [
262 262
                     // in the  /wp-content/plugins/(EE4 folder)/public/(current EE theme)/ folder within the plugin
263
-                    EE_PUBLIC . $current_theme,
263
+                    EE_PUBLIC.$current_theme,
264 264
                     // in the  /wp-content/plugins/(EE4 folder)/core/templates/(current EE theme)/ folder within the plugin
265
-                    EE_TEMPLATES . $current_theme,
265
+                    EE_TEMPLATES.$current_theme,
266 266
                     // or maybe relative from the plugin root: /wp-content/plugins/(EE4 folder)/
267 267
                     EE_PLUGIN_DIR_PATH,
268 268
                 ];
@@ -295,10 +295,10 @@  discard block
 block discarded – undo
295 295
                     );
296 296
                     if ($common_base_path !== '') {
297 297
                         // both paths have a common base, so just tack the filename onto our search path
298
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $file_name;
298
+                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path).$file_name;
299 299
                     } else {
300 300
                         // no common base path, so let's just concatenate
301
-                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path) . $template;
301
+                        $resolved_path = EEH_File::end_with_directory_separator($template_folder_path).$template;
302 302
                     }
303 303
                     // build up our template locations array by adding our resolved paths
304 304
                     $full_template_paths[] = $resolved_path;
@@ -306,7 +306,7 @@  discard block
 block discarded – undo
306 306
                 // if $template is an absolute path, then we'll tack it onto the start of our array so that it gets searched first
307 307
                 array_unshift($full_template_paths, $template);
308 308
                 // path to the directory of the current theme: /wp-content/themes/(current WP theme)/
309
-                array_unshift($full_template_paths, get_stylesheet_directory() . '/' . $file_name);
309
+                array_unshift($full_template_paths, get_stylesheet_directory().'/'.$file_name);
310 310
             }
311 311
             // filter final array of full template paths
312 312
             $full_template_paths = apply_filters(
@@ -363,7 +363,7 @@  discard block
 block discarded – undo
363 363
                 }
364 364
             }
365 365
             $common_base_path .= $directory;
366
-            $last_offset      = $index + 1;
366
+            $last_offset = $index + 1;
367 367
         }
368 368
         return substr($common_base_path, 0, -1);
369 369
     }
@@ -400,7 +400,7 @@  discard block
 block discarded – undo
400 400
         $template_args = (array) apply_filters('FHEE__EEH_Template__display_template__template_args', $template_args);
401 401
 
402 402
         // you gimme nuttin - YOU GET NUTTIN !!
403
-        if (! $template_path || ! is_readable($template_path)) {
403
+        if ( ! $template_path || ! is_readable($template_path)) {
404 404
             // ignore whether template is accessible ?
405 405
             if ($throw_exceptions) {
406 406
                 throw new DomainException(
@@ -437,11 +437,11 @@  discard block
 block discarded – undo
437 437
     public static function get_object_css_class($object = null, $prefix = '', $suffix = '')
438 438
     {
439 439
         // in the beginning...
440
-        $prefix = ! empty($prefix) ? rtrim($prefix, '-') . '-' : '';
440
+        $prefix = ! empty($prefix) ? rtrim($prefix, '-').'-' : '';
441 441
         // da muddle
442 442
         $class = '';
443 443
         // the end
444
-        $suffix = ! empty($suffix) ? '-' . ltrim($suffix, '-') : '';
444
+        $suffix = ! empty($suffix) ? '-'.ltrim($suffix, '-') : '';
445 445
         // is the passed object an EE object ?
446 446
         if ($object instanceof EE_Base_Class) {
447 447
             // grab the exact type of object
@@ -449,9 +449,9 @@  discard block
 block discarded – undo
449 449
             // depending on the type of object...
450 450
             // no specifics just yet...
451 451
             $class = strtolower(str_replace('_', '-', $obj_class));
452
-            $class .= method_exists($obj_class, 'name') ? '-' . sanitize_title($object->name()) : '';
452
+            $class .= method_exists($obj_class, 'name') ? '-'.sanitize_title($object->name()) : '';
453 453
         }
454
-        return $prefix . $class . $suffix;
454
+        return $prefix.$class.$suffix;
455 455
     }
456 456
 
457 457
 
@@ -486,7 +486,7 @@  discard block
 block discarded – undo
486 486
         // filter raw amount (allows 0.00 to be changed to "free" for example)
487 487
         $amount_formatted = apply_filters('FHEE__EEH_Template__format_currency__amount', $amount, $return_raw);
488 488
         // still a number, or was amount converted to a string like "free" ?
489
-        if (! is_float($amount_formatted)) {
489
+        if ( ! is_float($amount_formatted)) {
490 490
             return esc_html($amount_formatted);
491 491
         }
492 492
         try {
@@ -497,7 +497,7 @@  discard block
 block discarded – undo
497 497
             $mny = null;
498 498
         }
499 499
         // verify results
500
-        if (! $mny instanceof EE_Currency_Config) {
500
+        if ( ! $mny instanceof EE_Currency_Config) {
501 501
             // set default config country currency settings
502 502
             $mny = EE_Registry::instance()->CFG->currency instanceof EE_Currency_Config
503 503
                 ? EE_Registry::instance()->CFG->currency
@@ -506,16 +506,16 @@  discard block
 block discarded – undo
506 506
         // format float
507 507
         $amount_formatted = number_format($amount, $mny->dec_plc, $mny->dec_mrk, $mny->thsnds);
508 508
         // add formatting ?
509
-        if (! $return_raw) {
509
+        if ( ! $return_raw) {
510 510
             // add currency sign
511 511
             if ($mny->sign_b4) {
512 512
                 if ($amount >= 0) {
513
-                    $amount_formatted = $mny->sign . $amount_formatted;
513
+                    $amount_formatted = $mny->sign.$amount_formatted;
514 514
                 } else {
515
-                    $amount_formatted = '-' . $mny->sign . str_replace('-', '', $amount_formatted);
515
+                    $amount_formatted = '-'.$mny->sign.str_replace('-', '', $amount_formatted);
516 516
                 }
517 517
             } else {
518
-                $amount_formatted = $amount_formatted . $mny->sign;
518
+                $amount_formatted = $amount_formatted.$mny->sign;
519 519
             }
520 520
 
521 521
             // filter to allow global setting of display_code
@@ -526,7 +526,7 @@  discard block
 block discarded – undo
526 526
 
527 527
             // add currency code ?
528 528
             $amount_formatted = $display_code
529
-                ? $amount_formatted . ' <span class="' . $cur_code_span_class . '">' . $mny->code . '</span>'
529
+                ? $amount_formatted.' <span class="'.$cur_code_span_class.'">'.$mny->code.'</span>'
530 530
                 : $amount_formatted;
531 531
         }
532 532
         // filter results
@@ -562,7 +562,7 @@  discard block
 block discarded – undo
562 562
             $plural,
563 563
             $schema
564 564
         );
565
-        return $status[ $status_id ];
565
+        return $status[$status_id];
566 566
     }
567 567
 
568 568
 
@@ -579,14 +579,14 @@  discard block
 block discarded – undo
579 579
     public static function get_button_or_link($url, $label, $class = 'button button--primary', $icon = '', $title = '')
580 580
     {
581 581
         $icon_html = '';
582
-        if (! empty($icon)) {
582
+        if ( ! empty($icon)) {
583 583
             $dashicons = preg_split("(ee-icon |dashicons )", $icon);
584 584
             $dashicons = array_filter($dashicons);
585 585
             $count     = count($dashicons);
586 586
             $icon_html .= $count > 1 ? '<span class="ee-composite-dashicon">' : '';
587 587
             foreach ($dashicons as $dashicon) {
588
-                $type      = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
589
-                $icon_html .= '<span class="' . $type . $dashicon . '"></span>';
588
+                $type = strpos($dashicon, 'ee-icon') !== false ? 'ee-icon ' : 'dashicons ';
589
+                $icon_html .= '<span class="'.$type.$dashicon.'"></span>';
590 590
             }
591 591
             $icon_html .= $count > 1 ? '</span>' : '';
592 592
         }
@@ -625,18 +625,18 @@  discard block
 block discarded – undo
625 625
         $action  = $action ?: $request->getRequestParam('action', 'default', 'key');
626 626
 
627 627
 
628
-        $help_tab_lnk = $page . '-' . $action . '-' . $help_tab_id;
628
+        $help_tab_lnk = $page.'-'.$action.'-'.$help_tab_id;
629 629
         $icon         = ! $icon_style ? 'dashicons-editor-help' : $icon_style;
630 630
         $help_text    = ! $help_text ? '' : $help_text;
631 631
         return '
632
-            <a id="' . esc_attr($help_tab_lnk) . '"
633
-               class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon) . '"
632
+            <a id="' . esc_attr($help_tab_lnk).'"
633
+               class="espresso-help-tab-lnk ee-help-btn ee-aria-tooltip dashicons ' . esc_attr($icon).'"
634 634
                aria-label="' . esc_attr__(
635 635
                    'Click to open the \'Help\' tab for more information about this feature.',
636 636
                    'event_espresso'
637
-               ) . '"
637
+               ).'"
638 638
             >
639
-                ' . wp_kses($help_text, AllowedTags::getAllowedTags()) . '
639
+                ' . wp_kses($help_text, AllowedTags::getAllowedTags()).'
640 640
             </a>';
641 641
     }
642 642
 
@@ -657,7 +657,7 @@  discard block
 block discarded – undo
657 657
      */
658 658
     public static function status_legend($status_array, $active_status = '')
659 659
     {
660
-        if (! is_array($status_array)) {
660
+        if ( ! is_array($status_array)) {
661 661
             throw new EE_Error(
662 662
                 esc_html__(
663 663
                     'The EEH_Template::status_legend helper required the incoming status_array argument to be an array!',
@@ -669,17 +669,17 @@  discard block
 block discarded – undo
669 669
         $content = '
670 670
             <div class="ee-list-table-legend-container">
671 671
                 <h4 class="status-legend-title">
672
-                    ' . esc_html__('Status Legend', 'event_espresso') . '
672
+                    ' . esc_html__('Status Legend', 'event_espresso').'
673 673
                 </h4>
674 674
                 <dl class="ee-list-table-legend">';
675 675
 
676 676
         foreach ($status_array as $item => $status) {
677 677
             $active_class = $active_status == $status ? 'class="ee-is-active-status"' : '';
678
-            $content      .= '
679
-                    <dt id="' . esc_attr('ee-legend-item-tooltip-' . $item) . '" ' . $active_class . '>
680
-                        <span class="' . esc_attr('ee-status-legend ee-status-bg--' . $status) . '"></span>
678
+            $content .= '
679
+                    <dt id="' . esc_attr('ee-legend-item-tooltip-'.$item).'" '.$active_class.'>
680
+                        <span class="' . esc_attr('ee-status-legend ee-status-bg--'.$status).'"></span>
681 681
                         <span class="ee-legend-description">
682
-                            ' . EEH_Template::pretty_status($status, false, 'sentence') . '
682
+                            ' . EEH_Template::pretty_status($status, false, 'sentence').'
683 683
                         </span>
684 684
                     </dt>';
685 685
         }
@@ -822,8 +822,8 @@  discard block
 block discarded – undo
822 822
             ];
823 823
         } else {
824 824
             $items_label = [
825
-                'single' => '1 ' . esc_html($items_label['single']),
826
-                'plural' => '%s ' . esc_html($items_label['plural']),
825
+                'single' => '1 '.esc_html($items_label['single']),
826
+                'plural' => '%s '.esc_html($items_label['plural']),
827 827
             ];
828 828
         }
829 829
 
@@ -835,7 +835,7 @@  discard block
 block discarded – undo
835 835
 
836 836
         $item_label = $total_items > 1 ? sprintf($items_label['plural'], $total_items) : $items_label['single'];
837 837
 
838
-        $output = '<span class="displaying-num">' . $item_label . '</span>';
838
+        $output = '<span class="displaying-num">'.$item_label.'</span>';
839 839
 
840 840
         $disable_first = $current === 1 ? 'disabled' : '';
841 841
         $disable_last  = $current === $total_pages ? 'disabled' : '';
@@ -872,7 +872,7 @@  discard block
 block discarded – undo
872 872
             '<span class="total-pages">%s</span>',
873 873
             number_format_i18n($total_pages)
874 874
         );
875
-        $page_links[]     = sprintf(
875
+        $page_links[] = sprintf(
876 876
             _x('%3$s%1$s of %2$s%4$s', 'paging', 'event_espresso'),
877 877
             "{$html_current_page}<span class='paging-input-of'>",
878 878
             "</span>{$html_total_pages}",
@@ -896,14 +896,14 @@  discard block
 block discarded – undo
896 896
             '&raquo;'
897 897
         );
898 898
 
899
-        $output .= "\n" . '<span class="pagination-links">' . join("\n", $page_links) . '</span>';
899
+        $output .= "\n".'<span class="pagination-links">'.join("\n", $page_links).'</span>';
900 900
 
901 901
         $page_class = ' no-pages';
902 902
         if ($total_pages) {
903 903
             $page_class = $total_pages < 2 ? ' one-page' : '';
904 904
         }
905 905
 
906
-        return '<div class="tablenav"><div class="tablenav-pages' . $page_class . '">' . $output . '</div></div>';
906
+        return '<div class="tablenav"><div class="tablenav-pages'.$page_class.'">'.$output.'</div></div>';
907 907
     }
908 908
 
909 909
 
@@ -958,7 +958,7 @@  discard block
 block discarded – undo
958 958
         );
959 959
         $powered_by = apply_filters(
960 960
             'FHEE__EEH_Template__powered_by_event_espresso_text',
961
-            $admin ? 'Event Espresso - ' . EVENT_ESPRESSO_VERSION : 'Event Espresso'
961
+            $admin ? 'Event Espresso - '.EVENT_ESPRESSO_VERSION : 'Event Espresso'
962 962
         );
963 963
         $url        = add_query_arg($query_args, 'https://eventespresso.com/');
964 964
         $url        = apply_filters('FHEE__EEH_Template__powered_by_event_espresso__url', $url);
@@ -989,12 +989,12 @@  discard block
 block discarded – undo
989 989
      */
990 990
     public static function getScreenshotUrl($image_name)
991 991
     {
992
-        return esc_url_raw(EE_GLOBAL_ASSETS_URL . 'images/screenshots/' . $image_name . '.jpg');
992
+        return esc_url_raw(EE_GLOBAL_ASSETS_URL.'images/screenshots/'.$image_name.'.jpg');
993 993
     }
994 994
 }
995 995
 
996 996
 
997
-if (! function_exists('espresso_pagination')) {
997
+if ( ! function_exists('espresso_pagination')) {
998 998
     /**
999 999
      *    espresso_pagination
1000 1000
      *
@@ -1022,6 +1022,6 @@  discard block
 block discarded – undo
1022 1022
                 'add_fragment' => '',
1023 1023
             ]
1024 1024
         );
1025
-        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">' . $pagination . '</div>' : '';
1025
+        echo ! empty($pagination) ? '<div class="ee-pagination-dv ee-clear-float">'.$pagination.'</div>' : '';
1026 1026
     }
1027 1027
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Base.helper.php 1 patch
Indentation   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -11,40 +11,40 @@
 block discarded – undo
11 11
  */
12 12
 class EEH_Base
13 13
 {
14
-    /**
15
-     *  @var    array   $uri_segment_array  URL segments
16
-     */
14
+	/**
15
+	 *  @var    array   $uri_segment_array  URL segments
16
+	 */
17 17
 
18
-    /**
19
-     * override magic methods
20
-     * @return void
21
-     */
22
-    public function __set($a, $b)
23
-    {
24
-        return false;
25
-    }
26
-    public function __get($a)
27
-    {
28
-        return false;
29
-    }
30
-    public function __isset($a)
31
-    {
32
-        return false;
33
-    }
34
-    public function __unset($a)
35
-    {
36
-        return false;
37
-    }
38
-    public function __clone()
39
-    {
40
-        return false;
41
-    }
42
-    public function __wakeup()
43
-    {
44
-        return false;
45
-    }
46
-    public function __destruct()
47
-    {
48
-        return false;
49
-    }
18
+	/**
19
+	 * override magic methods
20
+	 * @return void
21
+	 */
22
+	public function __set($a, $b)
23
+	{
24
+		return false;
25
+	}
26
+	public function __get($a)
27
+	{
28
+		return false;
29
+	}
30
+	public function __isset($a)
31
+	{
32
+		return false;
33
+	}
34
+	public function __unset($a)
35
+	{
36
+		return false;
37
+	}
38
+	public function __clone()
39
+	{
40
+		return false;
41
+	}
42
+	public function __wakeup()
43
+	{
44
+		return false;
45
+	}
46
+	public function __destruct()
47
+	{
48
+		return false;
49
+	}
50 50
 }
Please login to merge, or discard this patch.
core/helpers/EEH_Array.helper.php 1 patch
Indentation   +319 added lines, -319 removed lines patch added patch discarded remove patch
@@ -11,349 +11,349 @@
 block discarded – undo
11 11
  */
12 12
 class EEH_Array extends EEH_Base
13 13
 {
14
-    /**
15
-     * This method basically works the same as the PHP core function array_diff except it allows you to compare arrays
16
-     * of EE_Base_Class objects NOTE: This will ONLY work on an array of EE_Base_Class objects
17
-     *
18
-     * @param array $array1 an array of objects
19
-     * @param array $array2 an array of objects
20
-     * @return array         an array of objects found in array 1 that aren't found in array 2.
21
-     * @uses self::_compare_objects as the custom method for array_udiff
22
-     * @uses array_udiff core php function for setting up our own array comparison
23
-     */
24
-    public static function object_array_diff(array $array1, array $array2): array
25
-    {
26
-        return array_udiff($array1, $array2, ['self', '_compare_objects']);
27
-    }
14
+	/**
15
+	 * This method basically works the same as the PHP core function array_diff except it allows you to compare arrays
16
+	 * of EE_Base_Class objects NOTE: This will ONLY work on an array of EE_Base_Class objects
17
+	 *
18
+	 * @param array $array1 an array of objects
19
+	 * @param array $array2 an array of objects
20
+	 * @return array         an array of objects found in array 1 that aren't found in array 2.
21
+	 * @uses self::_compare_objects as the custom method for array_udiff
22
+	 * @uses array_udiff core php function for setting up our own array comparison
23
+	 */
24
+	public static function object_array_diff(array $array1, array $array2): array
25
+	{
26
+		return array_udiff($array1, $array2, ['self', '_compare_objects']);
27
+	}
28 28
 
29 29
 
30
-    /**
31
-     * Given that $array is an array, determines if it's associative or numerically AND sequentially indexed
32
-     *
33
-     * @param array $array
34
-     * @return boolean
35
-     */
36
-    public static function is_associative_array(array $array): bool
37
-    {
38
-        return ! empty($array) && array_keys($array) !== range(0, count($array) - 1);
39
-    }
30
+	/**
31
+	 * Given that $array is an array, determines if it's associative or numerically AND sequentially indexed
32
+	 *
33
+	 * @param array $array
34
+	 * @return boolean
35
+	 */
36
+	public static function is_associative_array(array $array): bool
37
+	{
38
+		return ! empty($array) && array_keys($array) !== range(0, count($array) - 1);
39
+	}
40 40
 
41 41
 
42
-    /**
43
-     * Gets an item from the array and leave the array intact. Use in place of end()
44
-     * when you don't want to change the array
45
-     *
46
-     * @param array $array
47
-     * @return mixed what ever is in the array
48
-     */
49
-    public static function get_one_item_from_array(array $array)
50
-    {
51
-        $item = end($array);
52
-        reset($array);
53
-        return $item;
54
-    }
42
+	/**
43
+	 * Gets an item from the array and leave the array intact. Use in place of end()
44
+	 * when you don't want to change the array
45
+	 *
46
+	 * @param array $array
47
+	 * @return mixed what ever is in the array
48
+	 */
49
+	public static function get_one_item_from_array(array $array)
50
+	{
51
+		$item = end($array);
52
+		reset($array);
53
+		return $item;
54
+	}
55 55
 
56 56
 
57
-    /**
58
-     * Detects if this is a multi-dimensional array
59
-     * meaning that at least one top-level value is an array. Eg [ [], ...]
60
-     *
61
-     * @param mixed $array
62
-     * @return boolean
63
-     */
64
-    public static function is_multi_dimensional_array($array): bool
65
-    {
66
-        if (is_array($array)) {
67
-            foreach ($array as $item) {
68
-                if (is_array($item)) {
69
-                    return true; // yep, there's at least 2 levels to this array
70
-                }
71
-            }
72
-        }
73
-        return false; // there's only 1 level, or it's not an array at all!
74
-    }
57
+	/**
58
+	 * Detects if this is a multi-dimensional array
59
+	 * meaning that at least one top-level value is an array. Eg [ [], ...]
60
+	 *
61
+	 * @param mixed $array
62
+	 * @return boolean
63
+	 */
64
+	public static function is_multi_dimensional_array($array): bool
65
+	{
66
+		if (is_array($array)) {
67
+			foreach ($array as $item) {
68
+				if (is_array($item)) {
69
+					return true; // yep, there's at least 2 levels to this array
70
+				}
71
+			}
72
+		}
73
+		return false; // there's only 1 level, or it's not an array at all!
74
+	}
75 75
 
76 76
 
77
-    /**
78
-     * Shorthand for isset( $array[ $index ] ) ? $array[ $index ] : $default
79
-     *
80
-     * @param array $array
81
-     * @param mixed $index
82
-     * @param mixed $default
83
-     * @return mixed
84
-     */
85
-    public static function is_set(array $array, $index, $default)
86
-    {
87
-        return $array[ $index ] ?? $default;
88
-    }
77
+	/**
78
+	 * Shorthand for isset( $array[ $index ] ) ? $array[ $index ] : $default
79
+	 *
80
+	 * @param array $array
81
+	 * @param mixed $index
82
+	 * @param mixed $default
83
+	 * @return mixed
84
+	 */
85
+	public static function is_set(array $array, $index, $default)
86
+	{
87
+		return $array[ $index ] ?? $default;
88
+	}
89 89
 
90 90
 
91
-    /**
92
-     * Exactly like `maybe_unserialize`, but also accounts for a WP bug: http://core.trac.wordpress.org/ticket/26118
93
-     *
94
-     * @param mixed $value usually a string, but could be an array or object
95
-     * @return mixed the UN-serialized data
96
-     */
97
-    public static function maybe_unserialize($value)
98
-    {
99
-        $data = maybe_unserialize($value);
100
-        // it's possible that this still has serialized data if it's the session.
101
-        //  WP has a bug, http://core.trac.wordpress.org/ticket/26118 that doesn't unserialize this automatically.
102
-        $token = 'C';
103
-        $data  = is_string($data) ? trim($data) : $data;
104
-        if (is_string($data) && strlen($data) > 1 && $data[0] == $token && preg_match("/^$token:[0-9]+:/s", $data)) {
105
-            return unserialize($data);
106
-        }
107
-        return $data;
108
-    }
91
+	/**
92
+	 * Exactly like `maybe_unserialize`, but also accounts for a WP bug: http://core.trac.wordpress.org/ticket/26118
93
+	 *
94
+	 * @param mixed $value usually a string, but could be an array or object
95
+	 * @return mixed the UN-serialized data
96
+	 */
97
+	public static function maybe_unserialize($value)
98
+	{
99
+		$data = maybe_unserialize($value);
100
+		// it's possible that this still has serialized data if it's the session.
101
+		//  WP has a bug, http://core.trac.wordpress.org/ticket/26118 that doesn't unserialize this automatically.
102
+		$token = 'C';
103
+		$data  = is_string($data) ? trim($data) : $data;
104
+		if (is_string($data) && strlen($data) > 1 && $data[0] == $token && preg_match("/^$token:[0-9]+:/s", $data)) {
105
+			return unserialize($data);
106
+		}
107
+		return $data;
108
+	}
109 109
 
110 110
 
111
-    /**
112
-     * insert_into_array
113
-     *
114
-     * @param array           $target_array    the array to insert new data into
115
-     * @param array           $array_to_insert the new data to be inserted
116
-     * @param int|string|null $offset          a known key within $target_array where new data will be inserted
117
-     * @param bool            $add_before      whether to add new data before or after the offset key
118
-     * @param bool            $preserve_keys   whether or not to reset numerically indexed arrays
119
-     * @return array
120
-     */
121
-    public static function insert_into_array(
122
-        array $target_array = [],
123
-        array $array_to_insert = [],
124
-        $offset = null,
125
-        bool $add_before = true,
126
-        bool $preserve_keys = true
127
-    ): array {
128
-        $target_array_keys = array_keys($target_array);
129
-        // if no offset key was supplied
130
-        if (empty($offset)) {
131
-            // use start or end of $target_array based on whether we are adding before or not
132
-            $offset = $add_before ? 0 : count($target_array);
133
-        }
134
-        // if offset key is a string, then find the corresponding numeric location for that element
135
-        $offset = is_int($offset) ? $offset : array_search($offset, $target_array_keys, true);
136
-        // add one to the offset if adding after
137
-        $offset = $add_before ? $offset : $offset + 1;
138
-        // but ensure offset does not exceed the length of the array
139
-        $offset = $offset > count($target_array) ? count($target_array) : $offset;
140
-        // reindex array ???
141
-        if ($preserve_keys) {
142
-            // take a slice of the target array from the beginning till the offset,
143
-            // then add the new data
144
-            // then add another slice that starts at the offset and goes till the end
145
-            return array_slice($target_array, 0, $offset, true) + $array_to_insert + array_slice(
146
-                $target_array,
147
-                $offset,
148
-                null,
149
-                true
150
-            );
151
-        } else {
152
-            // since we don't want to preserve keys, we can use array_splice
153
-            array_splice($target_array, $offset, 0, $array_to_insert);
154
-            return $target_array;
155
-        }
156
-    }
111
+	/**
112
+	 * insert_into_array
113
+	 *
114
+	 * @param array           $target_array    the array to insert new data into
115
+	 * @param array           $array_to_insert the new data to be inserted
116
+	 * @param int|string|null $offset          a known key within $target_array where new data will be inserted
117
+	 * @param bool            $add_before      whether to add new data before or after the offset key
118
+	 * @param bool            $preserve_keys   whether or not to reset numerically indexed arrays
119
+	 * @return array
120
+	 */
121
+	public static function insert_into_array(
122
+		array $target_array = [],
123
+		array $array_to_insert = [],
124
+		$offset = null,
125
+		bool $add_before = true,
126
+		bool $preserve_keys = true
127
+	): array {
128
+		$target_array_keys = array_keys($target_array);
129
+		// if no offset key was supplied
130
+		if (empty($offset)) {
131
+			// use start or end of $target_array based on whether we are adding before or not
132
+			$offset = $add_before ? 0 : count($target_array);
133
+		}
134
+		// if offset key is a string, then find the corresponding numeric location for that element
135
+		$offset = is_int($offset) ? $offset : array_search($offset, $target_array_keys, true);
136
+		// add one to the offset if adding after
137
+		$offset = $add_before ? $offset : $offset + 1;
138
+		// but ensure offset does not exceed the length of the array
139
+		$offset = $offset > count($target_array) ? count($target_array) : $offset;
140
+		// reindex array ???
141
+		if ($preserve_keys) {
142
+			// take a slice of the target array from the beginning till the offset,
143
+			// then add the new data
144
+			// then add another slice that starts at the offset and goes till the end
145
+			return array_slice($target_array, 0, $offset, true) + $array_to_insert + array_slice(
146
+				$target_array,
147
+				$offset,
148
+				null,
149
+				true
150
+			);
151
+		} else {
152
+			// since we don't want to preserve keys, we can use array_splice
153
+			array_splice($target_array, $offset, 0, $array_to_insert);
154
+			return $target_array;
155
+		}
156
+	}
157 157
 
158 158
 
159
-    /**
160
-     * array_merge() is slow and should never be used while looping over data
161
-     * if you don't need to preserve keys from all arrays, then using a foreach loop is much faster
162
-     * so really this acts more like array_replace( $array1, $array2 )
163
-     * or a union with the arrays flipped ( $array2 + $array1 )
164
-     * this saves a few lines of code and improves readability
165
-     *
166
-     * @param array $array1
167
-     * @param array $array2
168
-     * @return array
169
-     */
170
-    public static function merge_arrays_and_overwrite_keys(array $array1, array $array2): array
171
-    {
172
-        foreach ($array2 as $key => $value) {
173
-            $array1[ $key ] = $value;
174
-        }
175
-        return $array1;
176
-    }
159
+	/**
160
+	 * array_merge() is slow and should never be used while looping over data
161
+	 * if you don't need to preserve keys from all arrays, then using a foreach loop is much faster
162
+	 * so really this acts more like array_replace( $array1, $array2 )
163
+	 * or a union with the arrays flipped ( $array2 + $array1 )
164
+	 * this saves a few lines of code and improves readability
165
+	 *
166
+	 * @param array $array1
167
+	 * @param array $array2
168
+	 * @return array
169
+	 */
170
+	public static function merge_arrays_and_overwrite_keys(array $array1, array $array2): array
171
+	{
172
+		foreach ($array2 as $key => $value) {
173
+			$array1[ $key ] = $value;
174
+		}
175
+		return $array1;
176
+	}
177 177
 
178 178
 
179
-    /**
180
-     * given a flat array like $array = array('A', 'B', 'C')
181
-     * will convert into a multidimensional array like $array[A][B][C]
182
-     * if $final_value is provided and is anything other than null,
183
-     * then that will be set as the value for the innermost array key
184
-     * like so: $array[A][B][C] = $final_value
185
-     *
186
-     * @param array $flat_array
187
-     * @param mixed $final_value
188
-     * @return array
189
-     */
190
-    public static function convert_array_values_to_keys(array $flat_array, $final_value = null): array
191
-    {
192
-        $multidimensional = [];
193
-        $reference        = &$multidimensional;
194
-        foreach ($flat_array as $key) {
195
-            $reference[ $key ] = [];
196
-            $reference         = &$reference[ $key ];
197
-        }
198
-        if ($final_value !== null) {
199
-            $reference = $final_value;
200
-        }
201
-        return $multidimensional;
202
-    }
179
+	/**
180
+	 * given a flat array like $array = array('A', 'B', 'C')
181
+	 * will convert into a multidimensional array like $array[A][B][C]
182
+	 * if $final_value is provided and is anything other than null,
183
+	 * then that will be set as the value for the innermost array key
184
+	 * like so: $array[A][B][C] = $final_value
185
+	 *
186
+	 * @param array $flat_array
187
+	 * @param mixed $final_value
188
+	 * @return array
189
+	 */
190
+	public static function convert_array_values_to_keys(array $flat_array, $final_value = null): array
191
+	{
192
+		$multidimensional = [];
193
+		$reference        = &$multidimensional;
194
+		foreach ($flat_array as $key) {
195
+			$reference[ $key ] = [];
196
+			$reference         = &$reference[ $key ];
197
+		}
198
+		if ($final_value !== null) {
199
+			$reference = $final_value;
200
+		}
201
+		return $multidimensional;
202
+	}
203 203
 
204 204
 
205
-    /**
206
-     * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
207
-     * @param array $array
208
-     * @return bool
209
-     */
210
-    public static function is_array_numerically_and_sequentially_indexed(array $array): bool
211
-    {
212
-        return empty($array) || array_keys($array) === range(0, count($array) - 1);
213
-    }
205
+	/**
206
+	 * @see http://stackoverflow.com/questions/173400/how-to-check-if-php-array-is-associative-or-sequential
207
+	 * @param array $array
208
+	 * @return bool
209
+	 */
210
+	public static function is_array_numerically_and_sequentially_indexed(array $array): bool
211
+	{
212
+		return empty($array) || array_keys($array) === range(0, count($array) - 1);
213
+	}
214 214
 
215 215
 
216
-    /**
217
-     * recursively walks through an array and adds slashes to all no array elements
218
-     *
219
-     * @param mixed $element
220
-     * @return array|string
221
-     * @since   4.10.29.p
222
-     */
223
-    public static function addSlashesRecursively($element)
224
-    {
225
-        if (is_array($element)) {
226
-            foreach ($element as $key => $value) {
227
-                $element[ $key ] = EEH_Array::addSlashesRecursively($value);
228
-            }
229
-            return $element;
230
-        }
231
-        return is_string($element) ? addslashes($element) : $element;
232
-    }
216
+	/**
217
+	 * recursively walks through an array and adds slashes to all no array elements
218
+	 *
219
+	 * @param mixed $element
220
+	 * @return array|string
221
+	 * @since   4.10.29.p
222
+	 */
223
+	public static function addSlashesRecursively($element)
224
+	{
225
+		if (is_array($element)) {
226
+			foreach ($element as $key => $value) {
227
+				$element[ $key ] = EEH_Array::addSlashesRecursively($value);
228
+			}
229
+			return $element;
230
+		}
231
+		return is_string($element) ? addslashes($element) : $element;
232
+	}
233 233
 
234 234
 
235
-    /**
236
-     * link https://stackoverflow.com/a/3877494
237
-     *
238
-     * @param array $array_1
239
-     * @param array $array_2
240
-     * @return array
241
-     * @since   5.0.0.p
242
-     */
243
-    public static function array_diff_recursive(array $array_1, array $array_2): array
244
-    {
245
-        $diff = [];
246
-        foreach ($array_1 as $key => $value) {
247
-            if (array_key_exists($key, $array_2)) {
248
-                if (is_array($value)) {
249
-                    $inner_diff = EEH_Array::array_diff_recursive($value, $array_2[ $key ]);
250
-                    if (count($inner_diff)) {
251
-                        $diff[ $key ] = $inner_diff;
252
-                    }
253
-                } else {
254
-                    if ($value != $array_2[ $key ]) {
255
-                        $diff[ $key ] = $value;
256
-                    }
257
-                }
258
-            } else {
259
-                $diff[ $key ] = $value;
260
-            }
261
-        }
262
-        return $diff;
263
-    }
235
+	/**
236
+	 * link https://stackoverflow.com/a/3877494
237
+	 *
238
+	 * @param array $array_1
239
+	 * @param array $array_2
240
+	 * @return array
241
+	 * @since   5.0.0.p
242
+	 */
243
+	public static function array_diff_recursive(array $array_1, array $array_2): array
244
+	{
245
+		$diff = [];
246
+		foreach ($array_1 as $key => $value) {
247
+			if (array_key_exists($key, $array_2)) {
248
+				if (is_array($value)) {
249
+					$inner_diff = EEH_Array::array_diff_recursive($value, $array_2[ $key ]);
250
+					if (count($inner_diff)) {
251
+						$diff[ $key ] = $inner_diff;
252
+					}
253
+				} else {
254
+					if ($value != $array_2[ $key ]) {
255
+						$diff[ $key ] = $value;
256
+					}
257
+				}
258
+			} else {
259
+				$diff[ $key ] = $value;
260
+			}
261
+		}
262
+		return $diff;
263
+	}
264 264
 
265 265
 
266
-    /**
267
-     * converts multidimensional arrays into a single depth associative array
268
-     * or converts arrays of any depth into a readable string representation
269
-     *
270
-     *  $example = [
271
-     *      'a' => 'A',
272
-     *      'b' => 'B',
273
-     *      'c' => [
274
-     *          'd' => 'D',
275
-     *          'e' => 'E',
276
-     *          'f' => [ 'G', 'H', 'I' ],
277
-     *      ],
278
-     *      [ 'J', 'K' ],
279
-     *      'L',
280
-     *      'M',
281
-     *      'n' => [
282
-     *          'o' => 'P'
283
-     *      ],
284
-     *  ];
285
-     *
286
-     *  print_r( EEH_Array::flattenArray($example) );
287
-     *
288
-     *  Array (
289
-     *      [a] => A
290
-     *      [b] => B
291
-     *      [c] => [ d:D, e:E, f:[ G, H, I ] ]
292
-     *      [0] => [ J, K ]
293
-     *      [1] => L
294
-     *      [2] => M
295
-     *      [n] => [ o:P ]
296
-     *  )
297
-     *
298
-     *  print_r( EEH_Array::flattenArray($example, true) );
299
-     *
300
-     *  "a:A, b:B, c:[ d:D, e:E, f:[ G, H, I ] ], [ J, K ], L, M, n:[ o:P ]"
301
-     *
302
-     * @param array $array      the array to be flattened
303
-     * @param bool  $to_string  [true] will flatten the entire array down into a string
304
-     *                          [false] will only flatten sub-arrays down into strings and return a array
305
-     * @param bool  $top_level  used for formatting purposes only, best to leave this alone as it's set internally
306
-     * @return array|false|string
307
-     * @since 5.0.0.p
308
-     */
309
-    public static function flattenArray(array $array, bool $to_string = false, bool $top_level = true)
310
-    {
311
-        $flat_array = [];
312
-        foreach ($array as $key => $value) {
313
-            $flat_array[ $key ] = is_array($value)
314
-                ? EEH_Array::flattenArray($value, true, false)
315
-                : $value;
316
-        }
317
-        if (! $to_string) {
318
-            return $flat_array;
319
-        }
320
-        $flat = '';
321
-        foreach ($flat_array as $key => $value) {
322
-            $flat .= is_int($key) ? "$value, " : "$key:$value, ";
323
-        }
324
-        $flat = substr($flat, 0, -2);
325
-        return $top_level ? $flat : "[ $flat ]";
326
-    }
266
+	/**
267
+	 * converts multidimensional arrays into a single depth associative array
268
+	 * or converts arrays of any depth into a readable string representation
269
+	 *
270
+	 *  $example = [
271
+	 *      'a' => 'A',
272
+	 *      'b' => 'B',
273
+	 *      'c' => [
274
+	 *          'd' => 'D',
275
+	 *          'e' => 'E',
276
+	 *          'f' => [ 'G', 'H', 'I' ],
277
+	 *      ],
278
+	 *      [ 'J', 'K' ],
279
+	 *      'L',
280
+	 *      'M',
281
+	 *      'n' => [
282
+	 *          'o' => 'P'
283
+	 *      ],
284
+	 *  ];
285
+	 *
286
+	 *  print_r( EEH_Array::flattenArray($example) );
287
+	 *
288
+	 *  Array (
289
+	 *      [a] => A
290
+	 *      [b] => B
291
+	 *      [c] => [ d:D, e:E, f:[ G, H, I ] ]
292
+	 *      [0] => [ J, K ]
293
+	 *      [1] => L
294
+	 *      [2] => M
295
+	 *      [n] => [ o:P ]
296
+	 *  )
297
+	 *
298
+	 *  print_r( EEH_Array::flattenArray($example, true) );
299
+	 *
300
+	 *  "a:A, b:B, c:[ d:D, e:E, f:[ G, H, I ] ], [ J, K ], L, M, n:[ o:P ]"
301
+	 *
302
+	 * @param array $array      the array to be flattened
303
+	 * @param bool  $to_string  [true] will flatten the entire array down into a string
304
+	 *                          [false] will only flatten sub-arrays down into strings and return a array
305
+	 * @param bool  $top_level  used for formatting purposes only, best to leave this alone as it's set internally
306
+	 * @return array|false|string
307
+	 * @since 5.0.0.p
308
+	 */
309
+	public static function flattenArray(array $array, bool $to_string = false, bool $top_level = true)
310
+	{
311
+		$flat_array = [];
312
+		foreach ($array as $key => $value) {
313
+			$flat_array[ $key ] = is_array($value)
314
+				? EEH_Array::flattenArray($value, true, false)
315
+				: $value;
316
+		}
317
+		if (! $to_string) {
318
+			return $flat_array;
319
+		}
320
+		$flat = '';
321
+		foreach ($flat_array as $key => $value) {
322
+			$flat .= is_int($key) ? "$value, " : "$key:$value, ";
323
+		}
324
+		$flat = substr($flat, 0, -2);
325
+		return $top_level ? $flat : "[ $flat ]";
326
+	}
327 327
 
328 328
 
329
-    /**
330
-     * Filters elements of an array using a callback function recursively.
331
-     *
332
-     * This method applies a user-supplied function to each element of the input array recursively.
333
-     * It preserves keys by default. The array is traversed in a depth-first manner.
334
-     * It also provides an option to remove empty elements.
335
-     *
336
-     * @param array    $array        The input array to filter.
337
-     * @param callable $filter       The callback function to use. If the function returns true,
338
-     *                               the current value from array is returned into the result array.
339
-     * @param bool     $remove_empty Optional parameter to remove empty elements. Default is false.
340
-     * @return array The filtered array.
341
-     */
342
-    public static function arrayFilterRecursive(array $array, callable $filter, bool $remove_empty = false): array
343
-    {
344
-        $filtered = [];
345
-        foreach ($array as $key => $value) {
346
-            if (is_array($value)) {
347
-                $value = EEH_Array::arrayFilterRecursive($value, $filter);
348
-                if (! ($remove_empty && empty($value))) {
349
-                    $filtered[ $key ] = $value;
350
-                }
351
-            } else {
352
-                if (! ($remove_empty && empty($value)) && $filter($value, $key)) {
353
-                    $filtered[ $key ] = $value;
354
-                }
355
-            }
356
-        }
357
-        return $filtered;
358
-    }
329
+	/**
330
+	 * Filters elements of an array using a callback function recursively.
331
+	 *
332
+	 * This method applies a user-supplied function to each element of the input array recursively.
333
+	 * It preserves keys by default. The array is traversed in a depth-first manner.
334
+	 * It also provides an option to remove empty elements.
335
+	 *
336
+	 * @param array    $array        The input array to filter.
337
+	 * @param callable $filter       The callback function to use. If the function returns true,
338
+	 *                               the current value from array is returned into the result array.
339
+	 * @param bool     $remove_empty Optional parameter to remove empty elements. Default is false.
340
+	 * @return array The filtered array.
341
+	 */
342
+	public static function arrayFilterRecursive(array $array, callable $filter, bool $remove_empty = false): array
343
+	{
344
+		$filtered = [];
345
+		foreach ($array as $key => $value) {
346
+			if (is_array($value)) {
347
+				$value = EEH_Array::arrayFilterRecursive($value, $filter);
348
+				if (! ($remove_empty && empty($value))) {
349
+					$filtered[ $key ] = $value;
350
+				}
351
+			} else {
352
+				if (! ($remove_empty && empty($value)) && $filter($value, $key)) {
353
+					$filtered[ $key ] = $value;
354
+				}
355
+			}
356
+		}
357
+		return $filtered;
358
+	}
359 359
 }
Please login to merge, or discard this patch.
core/EE_Maintenance_Mode.core.php 2 patches
Indentation   +512 added lines, -512 removed lines patch added patch discarded remove patch
@@ -19,524 +19,524 @@
 block discarded – undo
19 19
  */
20 20
 class EE_Maintenance_Mode implements ResettableInterface
21 21
 {
22
-    /**
23
-     * constants available to client code for interpreting the values of EE_Maintenance_Mode::level().
24
-     * STATUS_OFF means the site is NOT in maintenance mode (so everything's normal)
25
-     */
26
-    public const STATUS_OFF = 0;
27
-
28
-
29
-    /**
30
-     * STATUS_PUBLIC_ONLY means that the site's frontend EE code should be completely disabled
31
-     * but the admin backend should be running as normal. Maybe an admin can view the frontend though
32
-     */
33
-    public const STATUS_PUBLIC_ONLY = 1;
34
-
35
-    /**
36
-     * STATUS_FULL_SITE means the frontend AND EE backend code are disabled. The only system running
37
-     * is the maintenance mode stuff, which will require users to update all addons, and then finish running all
38
-     * migration scripts before taking the site out of maintenance mode
39
-     */
40
-    public const STATUS_FULL_SITE = 2;
41
-
42
-    /**
43
-     * the name of the option which stores the current level of maintenance mode
44
-     */
45
-    private const OPTION_NAME = 'ee_maintenance_mode';
46
-
47
-
48
-    protected LoaderInterface $loader;
49
-
50
-    private RequestInterface $request;
51
-
52
-    private static ?EE_Maintenance_Mode $_instance = null;
53
-
54
-    /**
55
-     * @var int
56
-     * @since 5.0.12.p
57
-     */
58
-    private int $status;
59
-
60
-    /**
61
-     * @var int
62
-     * @since 5.0.12.p
63
-     */
64
-    private int $admin_status;
65
-
66
-    /**
67
-     * true if current_user_can('administrator')
68
-     *
69
-     * @var bool
70
-     * @since 5.0.12.p
71
-     */
72
-    private bool $current_user_is_admin;
73
-
74
-    /**
75
-     * used to control updates to the WP options setting in the database
76
-     *
77
-     * @var bool
78
-     * @since 5.0.12.p
79
-     */
80
-    private bool $update_db;
81
-
82
-
83
-    /**
84
-     * @singleton method used to instantiate class object
85
-     * @param LoaderInterface|null  $loader
86
-     * @param RequestInterface|null $request
87
-     * @return EE_Maintenance_Mode|null
88
-     */
89
-    public static function instance(
90
-        ?LoaderInterface $loader = null,
91
-        ?RequestInterface $request = null
92
-    ): ?EE_Maintenance_Mode {
93
-        // check if class object is instantiated
94
-        if (! self::$_instance instanceof EE_Maintenance_Mode) {
95
-            self::$_instance = new EE_Maintenance_Mode($loader, $request);
96
-        }
97
-        return self::$_instance;
98
-    }
99
-
100
-
101
-    /**
102
-     * Resets maintenance mode (mostly just re-checks whether we should be in maintenance mode)
103
-     *
104
-     * @return EE_Maintenance_Mode|null
105
-     * @throws EE_Error
106
-     */
107
-    public static function reset(): ?EE_Maintenance_Mode
108
-    {
109
-        self::instance()->set_maintenance_mode_if_db_old();
110
-        self::instance()->initialize();
111
-        return self::instance();
112
-    }
113
-
114
-
115
-    /**
116
-     *private constructor to prevent direct creation
117
-     */
118
-    private function __construct(LoaderInterface $loader, RequestInterface $request)
119
-    {
120
-        $this->loader                = $loader;
121
-        $this->request               = $request;
122
-        $this->initialize();
123
-
124
-        // if M-Mode level 2 is engaged, we still need basic assets loaded
125
-        add_action('wp_enqueue_scripts', [$this, 'load_assets_required_for_m_mode']);
126
-        // shut 'er down for maintenance ?
127
-        add_filter('the_content', [$this, 'the_content'], 2);
128
-        // redirect ee menus to maintenance page
129
-        add_action('admin_page_access_denied', [$this, 'redirect_to_maintenance']);
130
-        // add powered by EE msg
131
-        add_action('shutdown', [$this, 'display_maintenance_mode_notice']);
132
-    }
133
-
134
-
135
-    private function initialize(): void
136
-    {
137
-        $this->current_user_is_admin = current_user_can('administrator');
138
-        // now make sure the status is set correctly everywhere
139
-        // (but don't update the db else we'll get into an infinite loop of updates)
140
-        $this->update_db = false;
141
-        $this->set_maintenance_level($this->loadStatusFromDatabase());
142
-        $this->update_db = true;
143
-    }
144
-
145
-
146
-    private function loadStatusFromDatabase(): int
147
-    {
148
-        return (int) get_option(EE_Maintenance_Mode::OPTION_NAME, EE_Maintenance_Mode::STATUS_OFF);
149
-    }
150
-
151
-
152
-    /**
153
-     * changes the maintenance mode level to reflect whether the current user is an admin or not.
154
-     * Determines whether we're in maintenance mode and what level. However, while the site
155
-     * is in level 1 maintenance, and an admin visits the frontend, this function makes it appear
156
-     * to them as if the site isn't in maintenance mode.
157
-     *      EE_Maintenance_Mode::STATUS_OFF => not in maintenance mode (in normal mode)
158
-     *      EE_Maintenance_Mode::STATUS_PUBLIC_ONLY=> frontend-only maintenance mode
159
-     *      EE_Maintenance_Mode::STATUS_FULL_SITE => frontend and backend maintenance mode
160
-     *
161
-     * @param int $status
162
-     * @return void
163
-     * @since 5.0.12.p
164
-     */
165
-    private function setAdminStatus(int $status)
166
-    {
167
-        if (
168
-            $status === EE_Maintenance_Mode::STATUS_PUBLIC_ONLY
169
-            && $this->current_user_is_admin
170
-            && ($this->request->isAjax() || ! $this->request->isAdmin())
171
-        ) {
172
-            $status = EE_Maintenance_Mode::STATUS_OFF;
173
-        }
174
-        $this->admin_status = $status;
175
-    }
176
-
177
-
178
-    public function real_level(): int
179
-    {
180
-        return $this->status;
181
-    }
182
-
183
-
184
-    /**
185
-     * @return int
186
-     */
187
-    public function level(): int
188
-    {
189
-        return $this->admin_status;
190
-    }
191
-
192
-
193
-    /**
194
-     * Determines if we need to put EE in maintenance mode because the database needs updating
195
-     *
196
-     * @return boolean true if DB is old and maintenance mode was triggered; false otherwise
197
-     * @throws EE_Error
198
-     */
199
-    public function set_maintenance_mode_if_db_old(): bool
200
-    {
201
-        /** @var EE_Data_Migration_Manager $data_migration_manager */
202
-        $data_migration_manager = $this->loader->getShared(EE_Data_Migration_Manager::class);
203
-        $scripts_that_should_run = $data_migration_manager->check_for_applicable_data_migration_scripts();
204
-        if (! empty($scripts_that_should_run)) { //  && $this->status !== EE_Maintenance_Mode::STATUS_FULL_SITE
205
-            $this->activateFullSiteMaintenanceMode();
206
-            return true;
207
-        }
208
-        if ($this->status === EE_Maintenance_Mode::STATUS_FULL_SITE) {
209
-            // we also want to handle the opposite: if the site is mm2, but there aren't any migrations to run
210
-            // then we shouldn't be in mm2. (Maybe an addon got deactivated?)
211
-            $this->deactivateMaintenanceMode();
212
-        }
213
-        return false;
214
-    }
215
-
216
-
217
-    /**
218
-     * Updates the maintenance level on the site
219
-     *
220
-     * @param int $level
221
-     * @return void
222
-     */
223
-    public function set_maintenance_level(int $level): void
224
-    {
225
-        switch ($level) {
226
-            case EE_Maintenance_Mode::STATUS_OFF:
227
-                $this->deactivateMaintenanceMode();
228
-                return;
229
-            case EE_Maintenance_Mode::STATUS_PUBLIC_ONLY:
230
-                $this->activatePublicOnlyMaintenanceMode();
231
-                return;
232
-            case EE_Maintenance_Mode::STATUS_FULL_SITE:
233
-                $this->activateFullSiteMaintenanceMode();
234
-                return;
235
-        }
236
-        throw new DomainException(
237
-            sprintf(
238
-                esc_html__(
239
-                    '"%1$s" is not valid a EE maintenance mode level. Please choose from one of the following: %2$s',
240
-                    'event_espresso'
241
-                ),
242
-                $level,
243
-                'EE_Maintenance_Mode::STATUS_OFF, EE_Maintenance_Mode::STATUS_PUBLIC_ONLY, EE_Maintenance_Mode::STATUS_FULL_SITE',
244
-            )
245
-        );
246
-    }
247
-
248
-
249
-    /**
250
-     * sets database status to online
251
-     * sets maintenance mode status to public only, unless current user is an admin, then maintenance mode is disabled
252
-     *
253
-     * @return void
254
-     * @since 5.0.12.p
255
-     */
256
-    public function activatePublicOnlyMaintenanceMode()
257
-    {
258
-        DbStatus::setOnline();
259
-        // disable maintenance mode for admins, otherwise enable public only maintenance mode
260
-        if ($this->current_user_is_admin) {
261
-            MaintenanceStatus::disableMaintenanceMode();
262
-        } else {
263
-            MaintenanceStatus::setPublicOnlyMaintenanceMode();
264
-        }
265
-        $this->updateMaintenaceModeStatus(EE_Maintenance_Mode::STATUS_PUBLIC_ONLY);
266
-    }
267
-
268
-
269
-    /**
270
-     * sets database status to offline
271
-     * sets maintenance mode status to full site
272
-     *
273
-     * @return void
274
-     * @since 5.0.12.p
275
-     */
276
-    public function activateFullSiteMaintenanceMode()
277
-    {
278
-        DbStatus::setOffline();
279
-        MaintenanceStatus::setFullSiteMaintenanceMode();
280
-        $this->updateMaintenaceModeStatus(EE_Maintenance_Mode::STATUS_FULL_SITE);
281
-    }
282
-
283
-
284
-    /**
285
-     * sets database status to online
286
-     * turns maintenance mode off
287
-     *
288
-     * @return void
289
-     * @since 5.0.12.p
290
-     */
291
-    public function deactivateMaintenanceMode()
292
-    {
293
-        DbStatus::setOnline();
294
-        MaintenanceStatus::disableMaintenanceMode();
295
-        $this->updateMaintenaceModeStatus(EE_Maintenance_Mode::STATUS_OFF);
296
-    }
297
-
298
-
299
-    private function updateMaintenaceModeStatus(int $status)
300
-    {
301
-        $this->status = $status;
302
-        $this->setAdminStatus($status);
303
-        if (! $this->update_db) {
304
-            return;
305
-        }
306
-        do_action('AHEE__EE_Maintenance_Mode__set_maintenance_level', $status);
307
-        update_option(EE_Maintenance_Mode::OPTION_NAME, $status);
308
-    }
309
-
310
-
311
-    /**
312
-     * returns TRUE if M-Mode is engaged and the current request is not for the admin
313
-     *
314
-     * @return bool
315
-     */
316
-    public static function disable_frontend_for_maintenance(): bool
317
-    {
318
-        return ! is_admin() && MaintenanceStatus::isNotDisabled();
319
-    }
320
-
321
-
322
-    /**
323
-     * @return void
324
-     */
325
-    public function load_assets_required_for_m_mode(): void
326
-    {
327
-        if (
328
-            $this->status === EE_Maintenance_Mode::STATUS_FULL_SITE
329
-            && ! wp_script_is('espresso_core')
330
-        ) {
331
-            wp_register_style(
332
-                'espresso_default',
333
-                EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
334
-                ['dashicons'],
335
-                EVENT_ESPRESSO_VERSION
336
-            );
337
-            wp_enqueue_style('espresso_default');
338
-            wp_register_script(
339
-                'espresso_core',
340
-                EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
341
-                ['jquery'],
342
-                EVENT_ESPRESSO_VERSION,
343
-                true
344
-            );
345
-            wp_enqueue_script('espresso_core');
346
-        }
347
-    }
348
-
349
-
350
-    /**
351
-     * replacement EE CPT template that displays message notifying site visitors
352
-     * that EE has been temporarily placed into maintenance mode
353
-     * does NOT get called on non-EE-CPT requests
354
-     *
355
-     * @return    string
356
-     */
357
-    public static function template_include(): string
358
-    {
359
-        // shut 'er down for maintenance ? then don't use any of our templates for our endpoints
360
-        return get_template_directory() . '/index.php';
361
-    }
362
-
363
-
364
-    /**
365
-     * displays message notifying site visitors that EE has been temporarily
366
-     * placed into maintenance mode when post_type != EE CPT
367
-     *
368
-     * @param string $the_content
369
-     * @return string
370
-     */
371
-    public function the_content(string $the_content): string
372
-    {
373
-        // check if M-mode is engaged and for EE shortcode
374
-        if ($this->admin_status && strpos($the_content, '[ESPRESSO_') !== false) {
375
-            // this can eventually be moved to a template, or edited via admin. But for now...
376
-            $the_content = sprintf(
377
-                esc_html__(
378
-                    '%sMaintenance Mode%sEvent Registration has been temporarily closed while system maintenance is being performed. We\'re sorry for any inconveniences this may have caused. Please try back again later.%s',
379
-                    'event_espresso'
380
-                ),
381
-                '<h3>',
382
-                '</h3><p>',
383
-                '</p>'
384
-            );
385
-        }
386
-        return $the_content;
387
-    }
388
-
389
-
390
-    /**
391
-     * displays message on frontend of site notifying admin that EE has been temporarily placed into maintenance mode
392
-     */
393
-    public function display_maintenance_mode_notice()
394
-    {
395
-        if (
396
-            ! $this->current_user_is_admin
397
-            || $this->status === EE_Maintenance_Mode::STATUS_OFF
398
-            || $this->request->isAdmin()
399
-            || $this->request->isAjax()
400
-            || ! did_action('AHEE__EE_System__load_core_configuration__complete')
401
-        ) {
402
-            return;
403
-        }
404
-        /** @var CurrentPage $current_page */
405
-        $current_page = $this->loader->getShared(CurrentPage::class);
406
-        if ($current_page->isEspressoPage()) {
407
-            printf(
408
-                esc_html__(
409
-                    '%sclose%sEvent Registration is currently disabled because Event Espresso has been placed into Maintenance Mode. To change Maintenance Mode settings, click here %sEE Maintenance Mode Admin Page%s',
410
-                    'event_espresso'
411
-                ),
412
-                '<div id="ee-m-mode-admin-notice-dv" class="ee-really-important-notice-dv"><a class="close-espresso-notice" title="',
413
-                '"><span class="dashicons dashicons-no"></span></a><p>',
414
-                ' &raquo; <a href="' . add_query_arg(
415
-                    ['page' => 'espresso_maintenance_settings'],
416
-                    admin_url('admin.php')
417
-                ) . '">',
418
-                '</a></p></div>'
419
-            );
420
-        }
421
-    }
422
-    // espresso-notices important-notice ee-attention
423
-
424
-
425
-    /**
426
-     * Redirects EE admin menu requests to the maintenance page
427
-     */
428
-    public function redirect_to_maintenance()
429
-    {
430
-        global $pagenow;
431
-        $page = $this->request->getRequestParam('page', '', DataType::STRING);
432
-        if (
433
-            $pagenow == 'admin.php'
434
-            && $page !== 'espresso_maintenance_settings'
435
-            && strpos($page, 'espresso_') !== false
436
-            && $this->status == EE_Maintenance_Mode::STATUS_FULL_SITE
437
-        ) {
438
-            EEH_URL::safeRedirectAndExit('admin.php?page=espresso_maintenance_settings');
439
-        }
440
-    }
441
-
442
-
443
-    /**
444
-     * override magic methods
445
-     */
446
-    final public function __destruct()
447
-    {
448
-    }
449
-
450
-
451
-    final public function __call($a, $b)
452
-    {
453
-    }
454
-
455
-
456
-    final public function __get($a)
457
-    {
458
-    }
459
-
460
-
461
-    final public function __set($a, $b)
462
-    {
463
-    }
464
-
465
-
466
-    final public function __isset($a)
467
-    {
468
-    }
469
-
470
-
471
-    final public function __unset($a)
472
-    {
473
-    }
474
-
475
-
476
-    final public function __sleep()
477
-    {
478
-        return [];
479
-    }
480
-
481
-
482
-    final public function __wakeup()
483
-    {
484
-    }
485
-
486
-
487
-    final public function __invoke()
488
-    {
489
-    }
490
-
491
-
492
-    final public static function __set_state($a = null)
493
-    {
494
-        return EE_Maintenance_Mode::instance();
495
-    }
496
-
497
-
498
-    final public function __clone()
499
-    {
500
-    }
501
-
502
-
503
-    final public static function __callStatic($a, $b)
504
-    {
505
-    }
22
+	/**
23
+	 * constants available to client code for interpreting the values of EE_Maintenance_Mode::level().
24
+	 * STATUS_OFF means the site is NOT in maintenance mode (so everything's normal)
25
+	 */
26
+	public const STATUS_OFF = 0;
27
+
28
+
29
+	/**
30
+	 * STATUS_PUBLIC_ONLY means that the site's frontend EE code should be completely disabled
31
+	 * but the admin backend should be running as normal. Maybe an admin can view the frontend though
32
+	 */
33
+	public const STATUS_PUBLIC_ONLY = 1;
34
+
35
+	/**
36
+	 * STATUS_FULL_SITE means the frontend AND EE backend code are disabled. The only system running
37
+	 * is the maintenance mode stuff, which will require users to update all addons, and then finish running all
38
+	 * migration scripts before taking the site out of maintenance mode
39
+	 */
40
+	public const STATUS_FULL_SITE = 2;
41
+
42
+	/**
43
+	 * the name of the option which stores the current level of maintenance mode
44
+	 */
45
+	private const OPTION_NAME = 'ee_maintenance_mode';
46
+
47
+
48
+	protected LoaderInterface $loader;
49
+
50
+	private RequestInterface $request;
51
+
52
+	private static ?EE_Maintenance_Mode $_instance = null;
53
+
54
+	/**
55
+	 * @var int
56
+	 * @since 5.0.12.p
57
+	 */
58
+	private int $status;
59
+
60
+	/**
61
+	 * @var int
62
+	 * @since 5.0.12.p
63
+	 */
64
+	private int $admin_status;
65
+
66
+	/**
67
+	 * true if current_user_can('administrator')
68
+	 *
69
+	 * @var bool
70
+	 * @since 5.0.12.p
71
+	 */
72
+	private bool $current_user_is_admin;
73
+
74
+	/**
75
+	 * used to control updates to the WP options setting in the database
76
+	 *
77
+	 * @var bool
78
+	 * @since 5.0.12.p
79
+	 */
80
+	private bool $update_db;
81
+
82
+
83
+	/**
84
+	 * @singleton method used to instantiate class object
85
+	 * @param LoaderInterface|null  $loader
86
+	 * @param RequestInterface|null $request
87
+	 * @return EE_Maintenance_Mode|null
88
+	 */
89
+	public static function instance(
90
+		?LoaderInterface $loader = null,
91
+		?RequestInterface $request = null
92
+	): ?EE_Maintenance_Mode {
93
+		// check if class object is instantiated
94
+		if (! self::$_instance instanceof EE_Maintenance_Mode) {
95
+			self::$_instance = new EE_Maintenance_Mode($loader, $request);
96
+		}
97
+		return self::$_instance;
98
+	}
99
+
100
+
101
+	/**
102
+	 * Resets maintenance mode (mostly just re-checks whether we should be in maintenance mode)
103
+	 *
104
+	 * @return EE_Maintenance_Mode|null
105
+	 * @throws EE_Error
106
+	 */
107
+	public static function reset(): ?EE_Maintenance_Mode
108
+	{
109
+		self::instance()->set_maintenance_mode_if_db_old();
110
+		self::instance()->initialize();
111
+		return self::instance();
112
+	}
113
+
114
+
115
+	/**
116
+	 *private constructor to prevent direct creation
117
+	 */
118
+	private function __construct(LoaderInterface $loader, RequestInterface $request)
119
+	{
120
+		$this->loader                = $loader;
121
+		$this->request               = $request;
122
+		$this->initialize();
123
+
124
+		// if M-Mode level 2 is engaged, we still need basic assets loaded
125
+		add_action('wp_enqueue_scripts', [$this, 'load_assets_required_for_m_mode']);
126
+		// shut 'er down for maintenance ?
127
+		add_filter('the_content', [$this, 'the_content'], 2);
128
+		// redirect ee menus to maintenance page
129
+		add_action('admin_page_access_denied', [$this, 'redirect_to_maintenance']);
130
+		// add powered by EE msg
131
+		add_action('shutdown', [$this, 'display_maintenance_mode_notice']);
132
+	}
133
+
134
+
135
+	private function initialize(): void
136
+	{
137
+		$this->current_user_is_admin = current_user_can('administrator');
138
+		// now make sure the status is set correctly everywhere
139
+		// (but don't update the db else we'll get into an infinite loop of updates)
140
+		$this->update_db = false;
141
+		$this->set_maintenance_level($this->loadStatusFromDatabase());
142
+		$this->update_db = true;
143
+	}
144
+
145
+
146
+	private function loadStatusFromDatabase(): int
147
+	{
148
+		return (int) get_option(EE_Maintenance_Mode::OPTION_NAME, EE_Maintenance_Mode::STATUS_OFF);
149
+	}
150
+
151
+
152
+	/**
153
+	 * changes the maintenance mode level to reflect whether the current user is an admin or not.
154
+	 * Determines whether we're in maintenance mode and what level. However, while the site
155
+	 * is in level 1 maintenance, and an admin visits the frontend, this function makes it appear
156
+	 * to them as if the site isn't in maintenance mode.
157
+	 *      EE_Maintenance_Mode::STATUS_OFF => not in maintenance mode (in normal mode)
158
+	 *      EE_Maintenance_Mode::STATUS_PUBLIC_ONLY=> frontend-only maintenance mode
159
+	 *      EE_Maintenance_Mode::STATUS_FULL_SITE => frontend and backend maintenance mode
160
+	 *
161
+	 * @param int $status
162
+	 * @return void
163
+	 * @since 5.0.12.p
164
+	 */
165
+	private function setAdminStatus(int $status)
166
+	{
167
+		if (
168
+			$status === EE_Maintenance_Mode::STATUS_PUBLIC_ONLY
169
+			&& $this->current_user_is_admin
170
+			&& ($this->request->isAjax() || ! $this->request->isAdmin())
171
+		) {
172
+			$status = EE_Maintenance_Mode::STATUS_OFF;
173
+		}
174
+		$this->admin_status = $status;
175
+	}
176
+
177
+
178
+	public function real_level(): int
179
+	{
180
+		return $this->status;
181
+	}
182
+
183
+
184
+	/**
185
+	 * @return int
186
+	 */
187
+	public function level(): int
188
+	{
189
+		return $this->admin_status;
190
+	}
191
+
192
+
193
+	/**
194
+	 * Determines if we need to put EE in maintenance mode because the database needs updating
195
+	 *
196
+	 * @return boolean true if DB is old and maintenance mode was triggered; false otherwise
197
+	 * @throws EE_Error
198
+	 */
199
+	public function set_maintenance_mode_if_db_old(): bool
200
+	{
201
+		/** @var EE_Data_Migration_Manager $data_migration_manager */
202
+		$data_migration_manager = $this->loader->getShared(EE_Data_Migration_Manager::class);
203
+		$scripts_that_should_run = $data_migration_manager->check_for_applicable_data_migration_scripts();
204
+		if (! empty($scripts_that_should_run)) { //  && $this->status !== EE_Maintenance_Mode::STATUS_FULL_SITE
205
+			$this->activateFullSiteMaintenanceMode();
206
+			return true;
207
+		}
208
+		if ($this->status === EE_Maintenance_Mode::STATUS_FULL_SITE) {
209
+			// we also want to handle the opposite: if the site is mm2, but there aren't any migrations to run
210
+			// then we shouldn't be in mm2. (Maybe an addon got deactivated?)
211
+			$this->deactivateMaintenanceMode();
212
+		}
213
+		return false;
214
+	}
215
+
216
+
217
+	/**
218
+	 * Updates the maintenance level on the site
219
+	 *
220
+	 * @param int $level
221
+	 * @return void
222
+	 */
223
+	public function set_maintenance_level(int $level): void
224
+	{
225
+		switch ($level) {
226
+			case EE_Maintenance_Mode::STATUS_OFF:
227
+				$this->deactivateMaintenanceMode();
228
+				return;
229
+			case EE_Maintenance_Mode::STATUS_PUBLIC_ONLY:
230
+				$this->activatePublicOnlyMaintenanceMode();
231
+				return;
232
+			case EE_Maintenance_Mode::STATUS_FULL_SITE:
233
+				$this->activateFullSiteMaintenanceMode();
234
+				return;
235
+		}
236
+		throw new DomainException(
237
+			sprintf(
238
+				esc_html__(
239
+					'"%1$s" is not valid a EE maintenance mode level. Please choose from one of the following: %2$s',
240
+					'event_espresso'
241
+				),
242
+				$level,
243
+				'EE_Maintenance_Mode::STATUS_OFF, EE_Maintenance_Mode::STATUS_PUBLIC_ONLY, EE_Maintenance_Mode::STATUS_FULL_SITE',
244
+			)
245
+		);
246
+	}
247
+
248
+
249
+	/**
250
+	 * sets database status to online
251
+	 * sets maintenance mode status to public only, unless current user is an admin, then maintenance mode is disabled
252
+	 *
253
+	 * @return void
254
+	 * @since 5.0.12.p
255
+	 */
256
+	public function activatePublicOnlyMaintenanceMode()
257
+	{
258
+		DbStatus::setOnline();
259
+		// disable maintenance mode for admins, otherwise enable public only maintenance mode
260
+		if ($this->current_user_is_admin) {
261
+			MaintenanceStatus::disableMaintenanceMode();
262
+		} else {
263
+			MaintenanceStatus::setPublicOnlyMaintenanceMode();
264
+		}
265
+		$this->updateMaintenaceModeStatus(EE_Maintenance_Mode::STATUS_PUBLIC_ONLY);
266
+	}
267
+
268
+
269
+	/**
270
+	 * sets database status to offline
271
+	 * sets maintenance mode status to full site
272
+	 *
273
+	 * @return void
274
+	 * @since 5.0.12.p
275
+	 */
276
+	public function activateFullSiteMaintenanceMode()
277
+	{
278
+		DbStatus::setOffline();
279
+		MaintenanceStatus::setFullSiteMaintenanceMode();
280
+		$this->updateMaintenaceModeStatus(EE_Maintenance_Mode::STATUS_FULL_SITE);
281
+	}
282
+
283
+
284
+	/**
285
+	 * sets database status to online
286
+	 * turns maintenance mode off
287
+	 *
288
+	 * @return void
289
+	 * @since 5.0.12.p
290
+	 */
291
+	public function deactivateMaintenanceMode()
292
+	{
293
+		DbStatus::setOnline();
294
+		MaintenanceStatus::disableMaintenanceMode();
295
+		$this->updateMaintenaceModeStatus(EE_Maintenance_Mode::STATUS_OFF);
296
+	}
297
+
298
+
299
+	private function updateMaintenaceModeStatus(int $status)
300
+	{
301
+		$this->status = $status;
302
+		$this->setAdminStatus($status);
303
+		if (! $this->update_db) {
304
+			return;
305
+		}
306
+		do_action('AHEE__EE_Maintenance_Mode__set_maintenance_level', $status);
307
+		update_option(EE_Maintenance_Mode::OPTION_NAME, $status);
308
+	}
309
+
310
+
311
+	/**
312
+	 * returns TRUE if M-Mode is engaged and the current request is not for the admin
313
+	 *
314
+	 * @return bool
315
+	 */
316
+	public static function disable_frontend_for_maintenance(): bool
317
+	{
318
+		return ! is_admin() && MaintenanceStatus::isNotDisabled();
319
+	}
320
+
321
+
322
+	/**
323
+	 * @return void
324
+	 */
325
+	public function load_assets_required_for_m_mode(): void
326
+	{
327
+		if (
328
+			$this->status === EE_Maintenance_Mode::STATUS_FULL_SITE
329
+			&& ! wp_script_is('espresso_core')
330
+		) {
331
+			wp_register_style(
332
+				'espresso_default',
333
+				EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
334
+				['dashicons'],
335
+				EVENT_ESPRESSO_VERSION
336
+			);
337
+			wp_enqueue_style('espresso_default');
338
+			wp_register_script(
339
+				'espresso_core',
340
+				EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
341
+				['jquery'],
342
+				EVENT_ESPRESSO_VERSION,
343
+				true
344
+			);
345
+			wp_enqueue_script('espresso_core');
346
+		}
347
+	}
348
+
349
+
350
+	/**
351
+	 * replacement EE CPT template that displays message notifying site visitors
352
+	 * that EE has been temporarily placed into maintenance mode
353
+	 * does NOT get called on non-EE-CPT requests
354
+	 *
355
+	 * @return    string
356
+	 */
357
+	public static function template_include(): string
358
+	{
359
+		// shut 'er down for maintenance ? then don't use any of our templates for our endpoints
360
+		return get_template_directory() . '/index.php';
361
+	}
362
+
363
+
364
+	/**
365
+	 * displays message notifying site visitors that EE has been temporarily
366
+	 * placed into maintenance mode when post_type != EE CPT
367
+	 *
368
+	 * @param string $the_content
369
+	 * @return string
370
+	 */
371
+	public function the_content(string $the_content): string
372
+	{
373
+		// check if M-mode is engaged and for EE shortcode
374
+		if ($this->admin_status && strpos($the_content, '[ESPRESSO_') !== false) {
375
+			// this can eventually be moved to a template, or edited via admin. But for now...
376
+			$the_content = sprintf(
377
+				esc_html__(
378
+					'%sMaintenance Mode%sEvent Registration has been temporarily closed while system maintenance is being performed. We\'re sorry for any inconveniences this may have caused. Please try back again later.%s',
379
+					'event_espresso'
380
+				),
381
+				'<h3>',
382
+				'</h3><p>',
383
+				'</p>'
384
+			);
385
+		}
386
+		return $the_content;
387
+	}
388
+
389
+
390
+	/**
391
+	 * displays message on frontend of site notifying admin that EE has been temporarily placed into maintenance mode
392
+	 */
393
+	public function display_maintenance_mode_notice()
394
+	{
395
+		if (
396
+			! $this->current_user_is_admin
397
+			|| $this->status === EE_Maintenance_Mode::STATUS_OFF
398
+			|| $this->request->isAdmin()
399
+			|| $this->request->isAjax()
400
+			|| ! did_action('AHEE__EE_System__load_core_configuration__complete')
401
+		) {
402
+			return;
403
+		}
404
+		/** @var CurrentPage $current_page */
405
+		$current_page = $this->loader->getShared(CurrentPage::class);
406
+		if ($current_page->isEspressoPage()) {
407
+			printf(
408
+				esc_html__(
409
+					'%sclose%sEvent Registration is currently disabled because Event Espresso has been placed into Maintenance Mode. To change Maintenance Mode settings, click here %sEE Maintenance Mode Admin Page%s',
410
+					'event_espresso'
411
+				),
412
+				'<div id="ee-m-mode-admin-notice-dv" class="ee-really-important-notice-dv"><a class="close-espresso-notice" title="',
413
+				'"><span class="dashicons dashicons-no"></span></a><p>',
414
+				' &raquo; <a href="' . add_query_arg(
415
+					['page' => 'espresso_maintenance_settings'],
416
+					admin_url('admin.php')
417
+				) . '">',
418
+				'</a></p></div>'
419
+			);
420
+		}
421
+	}
422
+	// espresso-notices important-notice ee-attention
423
+
424
+
425
+	/**
426
+	 * Redirects EE admin menu requests to the maintenance page
427
+	 */
428
+	public function redirect_to_maintenance()
429
+	{
430
+		global $pagenow;
431
+		$page = $this->request->getRequestParam('page', '', DataType::STRING);
432
+		if (
433
+			$pagenow == 'admin.php'
434
+			&& $page !== 'espresso_maintenance_settings'
435
+			&& strpos($page, 'espresso_') !== false
436
+			&& $this->status == EE_Maintenance_Mode::STATUS_FULL_SITE
437
+		) {
438
+			EEH_URL::safeRedirectAndExit('admin.php?page=espresso_maintenance_settings');
439
+		}
440
+	}
441
+
442
+
443
+	/**
444
+	 * override magic methods
445
+	 */
446
+	final public function __destruct()
447
+	{
448
+	}
449
+
450
+
451
+	final public function __call($a, $b)
452
+	{
453
+	}
454
+
455
+
456
+	final public function __get($a)
457
+	{
458
+	}
459
+
460
+
461
+	final public function __set($a, $b)
462
+	{
463
+	}
464
+
465
+
466
+	final public function __isset($a)
467
+	{
468
+	}
469
+
470
+
471
+	final public function __unset($a)
472
+	{
473
+	}
474
+
475
+
476
+	final public function __sleep()
477
+	{
478
+		return [];
479
+	}
480
+
481
+
482
+	final public function __wakeup()
483
+	{
484
+	}
485
+
486
+
487
+	final public function __invoke()
488
+	{
489
+	}
490
+
491
+
492
+	final public static function __set_state($a = null)
493
+	{
494
+		return EE_Maintenance_Mode::instance();
495
+	}
496
+
497
+
498
+	final public function __clone()
499
+	{
500
+	}
501
+
502
+
503
+	final public static function __callStatic($a, $b)
504
+	{
505
+	}
506 506
 
507 507
 
508
-    /************************ @DEPRECATED ********************** */
508
+	/************************ @DEPRECATED ********************** */
509 509
 
510
-    /**
511
-     * @depecated 5.0.12.p
512
-     */
513
-    const level_0_not_in_maintenance = 0;
510
+	/**
511
+	 * @depecated 5.0.12.p
512
+	 */
513
+	const level_0_not_in_maintenance = 0;
514 514
 
515
-    /**
516
-     * @depecated 5.0.12.p
517
-     */
518
-    const level_1_frontend_only_maintenance = 1;
515
+	/**
516
+	 * @depecated 5.0.12.p
517
+	 */
518
+	const level_1_frontend_only_maintenance = 1;
519 519
 
520
-    /**
521
-     * @depecated 5.0.12.p
522
-     */
523
-    const level_2_complete_maintenance = 2;
520
+	/**
521
+	 * @depecated 5.0.12.p
522
+	 */
523
+	const level_2_complete_maintenance = 2;
524 524
 
525
-    /**
526
-     * @depecated 5.0.12.p
527
-     */
528
-    const option_name_maintenance_mode = 'ee_maintenance_mode';
525
+	/**
526
+	 * @depecated 5.0.12.p
527
+	 */
528
+	const option_name_maintenance_mode = 'ee_maintenance_mode';
529 529
 
530 530
 
531
-    /**
532
-     * Returns whether the models reportedly are able to run queries or not
533
-     * (ie, if the system thinks their tables are present and up-to-date).
534
-     *
535
-     * @return boolean
536
-     * @depecated 5.0.12.p
537
-     */
538
-    public function models_can_query(): bool
539
-    {
540
-        return DbStatus::isOnline();
541
-    }
531
+	/**
532
+	 * Returns whether the models reportedly are able to run queries or not
533
+	 * (ie, if the system thinks their tables are present and up-to-date).
534
+	 *
535
+	 * @return boolean
536
+	 * @depecated 5.0.12.p
537
+	 */
538
+	public function models_can_query(): bool
539
+	{
540
+		return DbStatus::isOnline();
541
+	}
542 542
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -91,7 +91,7 @@  discard block
 block discarded – undo
91 91
         ?RequestInterface $request = null
92 92
     ): ?EE_Maintenance_Mode {
93 93
         // check if class object is instantiated
94
-        if (! self::$_instance instanceof EE_Maintenance_Mode) {
94
+        if ( ! self::$_instance instanceof EE_Maintenance_Mode) {
95 95
             self::$_instance = new EE_Maintenance_Mode($loader, $request);
96 96
         }
97 97
         return self::$_instance;
@@ -201,7 +201,7 @@  discard block
 block discarded – undo
201 201
         /** @var EE_Data_Migration_Manager $data_migration_manager */
202 202
         $data_migration_manager = $this->loader->getShared(EE_Data_Migration_Manager::class);
203 203
         $scripts_that_should_run = $data_migration_manager->check_for_applicable_data_migration_scripts();
204
-        if (! empty($scripts_that_should_run)) { //  && $this->status !== EE_Maintenance_Mode::STATUS_FULL_SITE
204
+        if ( ! empty($scripts_that_should_run)) { //  && $this->status !== EE_Maintenance_Mode::STATUS_FULL_SITE
205 205
             $this->activateFullSiteMaintenanceMode();
206 206
             return true;
207 207
         }
@@ -300,7 +300,7 @@  discard block
 block discarded – undo
300 300
     {
301 301
         $this->status = $status;
302 302
         $this->setAdminStatus($status);
303
-        if (! $this->update_db) {
303
+        if ( ! $this->update_db) {
304 304
             return;
305 305
         }
306 306
         do_action('AHEE__EE_Maintenance_Mode__set_maintenance_level', $status);
@@ -330,14 +330,14 @@  discard block
 block discarded – undo
330 330
         ) {
331 331
             wp_register_style(
332 332
                 'espresso_default',
333
-                EE_GLOBAL_ASSETS_URL . 'css/espresso_default.css',
333
+                EE_GLOBAL_ASSETS_URL.'css/espresso_default.css',
334 334
                 ['dashicons'],
335 335
                 EVENT_ESPRESSO_VERSION
336 336
             );
337 337
             wp_enqueue_style('espresso_default');
338 338
             wp_register_script(
339 339
                 'espresso_core',
340
-                EE_GLOBAL_ASSETS_URL . 'scripts/espresso_core.js',
340
+                EE_GLOBAL_ASSETS_URL.'scripts/espresso_core.js',
341 341
                 ['jquery'],
342 342
                 EVENT_ESPRESSO_VERSION,
343 343
                 true
@@ -357,7 +357,7 @@  discard block
 block discarded – undo
357 357
     public static function template_include(): string
358 358
     {
359 359
         // shut 'er down for maintenance ? then don't use any of our templates for our endpoints
360
-        return get_template_directory() . '/index.php';
360
+        return get_template_directory().'/index.php';
361 361
     }
362 362
 
363 363
 
@@ -411,10 +411,10 @@  discard block
 block discarded – undo
411 411
                 ),
412 412
                 '<div id="ee-m-mode-admin-notice-dv" class="ee-really-important-notice-dv"><a class="close-espresso-notice" title="',
413 413
                 '"><span class="dashicons dashicons-no"></span></a><p>',
414
-                ' &raquo; <a href="' . add_query_arg(
414
+                ' &raquo; <a href="'.add_query_arg(
415 415
                     ['page' => 'espresso_maintenance_settings'],
416 416
                     admin_url('admin.php')
417
-                ) . '">',
417
+                ).'">',
418 418
                 '</a></p></div>'
419 419
             );
420 420
         }
Please login to merge, or discard this patch.
core/EE_Psr4AutoloaderInit.core.php 1 patch
Indentation   +33 added lines, -33 removed lines patch added patch discarded remove patch
@@ -13,42 +13,42 @@
 block discarded – undo
13 13
  */
14 14
 class EE_Psr4AutoloaderInit
15 15
 {
16
-    protected static ?Psr4Autoloader $psr4_loader = null;
16
+	protected static ?Psr4Autoloader $psr4_loader = null;
17 17
 
18
-    private static bool $initialized = false;
18
+	private static bool $initialized = false;
19 19
 
20 20
 
21
-    /**
22
-     * @return void
23
-     * @throws EE_Error
24
-     */
25
-    public function initializeAutoloader()
26
-    {
27
-        if (! EE_Psr4AutoloaderInit::$initialized) {
28
-            // register the base directories for the namespace prefix
29
-            $psr4_loader = EE_Psr4AutoloaderInit::psr4_loader();
30
-            $psr4_loader->addNamespace('EventEspresso', EE_PLUGIN_DIR_PATH);
31
-            $psr4_loader->addNamespace('EventEspressoBatchRequest', EE_LIBRARIES . 'batch');
32
-            $psr4_loader->addNamespace('EventEspressoVendor', EE_THIRD_PARTY);
33
-            do_action('AHEE__EE_Psr4AutoloaderInit__initializeAutoloader', $psr4_loader);
34
-            EE_Psr4AutoloaderInit::$initialized = true;
35
-        }
36
-    }
21
+	/**
22
+	 * @return void
23
+	 * @throws EE_Error
24
+	 */
25
+	public function initializeAutoloader()
26
+	{
27
+		if (! EE_Psr4AutoloaderInit::$initialized) {
28
+			// register the base directories for the namespace prefix
29
+			$psr4_loader = EE_Psr4AutoloaderInit::psr4_loader();
30
+			$psr4_loader->addNamespace('EventEspresso', EE_PLUGIN_DIR_PATH);
31
+			$psr4_loader->addNamespace('EventEspressoBatchRequest', EE_LIBRARIES . 'batch');
32
+			$psr4_loader->addNamespace('EventEspressoVendor', EE_THIRD_PARTY);
33
+			do_action('AHEE__EE_Psr4AutoloaderInit__initializeAutoloader', $psr4_loader);
34
+			EE_Psr4AutoloaderInit::$initialized = true;
35
+		}
36
+	}
37 37
 
38 38
 
39
-    /**
40
-     * @return Psr4Autoloader
41
-     * @throws EE_Error
42
-     */
43
-    public static function psr4_loader(): Psr4Autoloader
44
-    {
45
-        if (! EE_Psr4AutoloaderInit::$psr4_loader instanceof Psr4Autoloader) {
46
-            // instantiate PSR4 autoloader
47
-            espresso_load_required('Psr4Autoloader', __DIR__ . '/Psr4Autoloader.php');
48
-            EE_Psr4AutoloaderInit::$psr4_loader = new Psr4Autoloader();
49
-            // register the autoloader
50
-            EE_Psr4AutoloaderInit::$psr4_loader->register();
51
-        }
52
-        return EE_Psr4AutoloaderInit::$psr4_loader;
53
-    }
39
+	/**
40
+	 * @return Psr4Autoloader
41
+	 * @throws EE_Error
42
+	 */
43
+	public static function psr4_loader(): Psr4Autoloader
44
+	{
45
+		if (! EE_Psr4AutoloaderInit::$psr4_loader instanceof Psr4Autoloader) {
46
+			// instantiate PSR4 autoloader
47
+			espresso_load_required('Psr4Autoloader', __DIR__ . '/Psr4Autoloader.php');
48
+			EE_Psr4AutoloaderInit::$psr4_loader = new Psr4Autoloader();
49
+			// register the autoloader
50
+			EE_Psr4AutoloaderInit::$psr4_loader->register();
51
+		}
52
+		return EE_Psr4AutoloaderInit::$psr4_loader;
53
+	}
54 54
 }
Please login to merge, or discard this patch.