Completed
Branch barista (d34d0c)
by
unknown
37:41 queued 27:59
created
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 2 patches
Indentation   +1405 added lines, -1405 removed lines patch added patch discarded remove patch
@@ -16,1409 +16,1409 @@
 block discarded – undo
16 16
 class Extend_Events_Admin_Page extends Events_Admin_Page
17 17
 {
18 18
 
19
-    /**
20
-     * @var EE_Admin_Config
21
-     */
22
-    protected $admin_config;
23
-
24
-    /**
25
-     * @var AdvancedEditorAdminFormSection
26
-     */
27
-    protected $advanced_editor_admin_form;
28
-
29
-
30
-    /**
31
-     * Extend_Events_Admin_Page constructor.
32
-     *
33
-     * @param bool $routing
34
-     * @throws ReflectionException
35
-     */
36
-    public function __construct($routing = true)
37
-    {
38
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
39
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
40
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
41
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
42
-        }
43
-        parent::__construct($routing);
44
-        $this->admin_config = $this->loader->getShared('EE_Admin_Config');
45
-    }
46
-
47
-
48
-    /**
49
-     * Sets routes.
50
-     *
51
-     * @throws EE_Error
52
-     * @throws InvalidArgumentException
53
-     * @throws InvalidDataTypeException
54
-     * @throws InvalidInterfaceException
55
-     * @throws Exception
56
-     */
57
-    protected function _extend_page_config()
58
-    {
59
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
60
-        // is there a evt_id in the request?
61
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
62
-            ? $this->_req_data['EVT_ID']
63
-            : 0;
64
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
65
-        // tkt_id?
66
-        $tkt_id = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
67
-            ? $this->_req_data['TKT_ID']
68
-            : 0;
69
-        $new_page_routes = array(
70
-            'duplicate_event'          => array(
71
-                'func'       => '_duplicate_event',
72
-                'capability' => 'ee_edit_event',
73
-                'obj_id'     => $evt_id,
74
-                'noheader'   => true,
75
-            ),
76
-            'import_page'              => array(
77
-                'func'       => '_import_page',
78
-                'capability' => 'import',
79
-            ),
80
-            'import'                   => array(
81
-                'func'       => '_import_events',
82
-                'capability' => 'import',
83
-                'noheader'   => true,
84
-            ),
85
-            'import_events'            => array(
86
-                'func'       => '_import_events',
87
-                'capability' => 'import',
88
-                'noheader'   => true,
89
-            ),
90
-            'export_events'            => array(
91
-                'func'       => '_events_export',
92
-                'capability' => 'export',
93
-                'noheader'   => true,
94
-            ),
95
-            'export_categories'        => array(
96
-                'func'       => '_categories_export',
97
-                'capability' => 'export',
98
-                'noheader'   => true,
99
-            ),
100
-            'sample_export_file'       => array(
101
-                'func'       => '_sample_export_file',
102
-                'capability' => 'export',
103
-                'noheader'   => true,
104
-            ),
105
-            'update_template_settings' => array(
106
-                'func'       => '_update_template_settings',
107
-                'capability' => 'manage_options',
108
-                'noheader'   => true,
109
-            ),
110
-        );        // don't load these meta boxes if using the advanced editor
111
-        if (! $this->admin_config->useAdvancedEditor()) {
112
-            $this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
113
-            $this->_page_config['edit']['metaboxes'][] = '_premium_event_editor_meta_boxes';
114
-            $this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
115
-            $this->_page_config['edit']['qtips'][] = 'EE_Event_Editor_Tips';
116
-
117
-            $legacy_editor_page_routes = [
118
-                'ticket_list_table' => [
119
-                    'func'       => '_tickets_overview_list_table',
120
-                    'capability' => 'ee_read_default_tickets',
121
-                ],
122
-                'trash_ticket'      => [
123
-                    'func'       => '_trash_or_restore_ticket',
124
-                    'capability' => 'ee_delete_default_ticket',
125
-                    'obj_id'     => $tkt_id,
126
-                    'noheader'   => true,
127
-                    'args'       => ['trash' => true],
128
-                ],
129
-                'trash_tickets'     => [
130
-                    'func'       => '_trash_or_restore_ticket',
131
-                    'capability' => 'ee_delete_default_tickets',
132
-                    'noheader'   => true,
133
-                    'args'       => ['trash' => true],
134
-                ],
135
-                'restore_ticket'    => [
136
-                    'func'       => '_trash_or_restore_ticket',
137
-                    'capability' => 'ee_delete_default_ticket',
138
-                    'obj_id'     => $tkt_id,
139
-                    'noheader'   => true,
140
-                ],
141
-                'restore_tickets'   => [
142
-                    'func'       => '_trash_or_restore_ticket',
143
-                    'capability' => 'ee_delete_default_tickets',
144
-                    'noheader'   => true,
145
-                ],
146
-                'delete_ticket'     => [
147
-                    'func'       => '_delete_ticket',
148
-                    'capability' => 'ee_delete_default_ticket',
149
-                    'obj_id'     => $tkt_id,
150
-                    'noheader'   => true,
151
-                ],
152
-                'delete_tickets'    => [
153
-                    'func'       => '_delete_ticket',
154
-                    'capability' => 'ee_delete_default_tickets',
155
-                    'noheader'   => true,
156
-                ],
157
-            ];
158
-            $new_page_routes = array_merge($new_page_routes, $legacy_editor_page_routes);
159
-        }
160
-
161
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
162
-        // partial route/config override
163
-        $this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
164
-        $this->_page_config['default']['list_table'] = 'Extend_Events_Admin_List_Table';
165
-        // add tickets tab but only if there are more than one default ticket!
166
-        $tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
167
-            array(array('TKT_is_default' => 1)),
168
-            'TKT_ID',
169
-            true
170
-        );
171
-        if ($tkt_count > 1) {
172
-            $new_page_config = array(
173
-                'ticket_list_table' => array(
174
-                    'nav'           => array(
175
-                        'label' => esc_html__('Default Tickets', 'event_espresso'),
176
-                        'order' => 60,
177
-                    ),
178
-                    'list_table'    => 'Tickets_List_Table',
179
-                    'require_nonce' => false,
180
-                ),
181
-            );
182
-        }
183
-        // template settings
184
-        $new_page_config['template_settings'] = array(
185
-            'nav'           => array(
186
-                'label' => esc_html__('Templates', 'event_espresso'),
187
-                'order' => 30,
188
-            ),
189
-            'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
190
-            'help_tabs'     => array(
191
-                'general_settings_templates_help_tab' => array(
192
-                    'title'    => esc_html__('Templates', 'event_espresso'),
193
-                    'filename' => 'general_settings_templates',
194
-                ),
195
-            ),
196
-            'help_tour'     => array('Templates_Help_Tour'),
197
-            'require_nonce' => false,
198
-        );
199
-        $this->_page_config = array_merge($this->_page_config, $new_page_config);
200
-        // add filters and actions
201
-        // modifying _views
202
-        add_filter(
203
-            'FHEE_event_datetime_metabox_add_additional_date_time_template',
204
-            array($this, 'add_additional_datetime_button'),
205
-            10,
206
-            2
207
-        );
208
-        add_filter(
209
-            'FHEE_event_datetime_metabox_clone_button_template',
210
-            array($this, 'add_datetime_clone_button'),
211
-            10,
212
-            2
213
-        );
214
-        add_filter(
215
-            'FHEE_event_datetime_metabox_timezones_template',
216
-            array($this, 'datetime_timezones_template'),
217
-            10,
218
-            2
219
-        );
220
-        // filters for event list table
221
-        add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
222
-        add_filter(
223
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
224
-            array($this, 'extra_list_table_actions'),
225
-            10,
226
-            2
227
-        );
228
-        // legend item
229
-        add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
230
-        add_action('admin_init', array($this, 'admin_init'));
231
-       // load additional handlers
232
-        $this->handleActionRequest();
233
-    }
234
-
235
-
236
-    private function getRequestAction()
237
-    {
238
-        return isset($this->_req_data['action']) ? sanitize_key($this->_req_data['action']) : null;
239
-    }
240
-
241
-
242
-    /**
243
-     * @throws Exception
244
-     */
245
-    private function handleActionRequest()
246
-    {
247
-        $action = $this->getRequestAction();
248
-        if ($action) {
249
-            // setup Advanced Editor ???
250
-            if ($action === 'default_event_settings' || $action === 'update_default_event_settings') {
251
-                $this->advanced_editor_admin_form = $this->loader->getShared(
252
-                    'EventEspresso\core\domain\services\admin\events\default_settings\AdvancedEditorAdminFormSection'
253
-                );
254
-            }
255
-        }
256
-    }
257
-
258
-
259
-    /**
260
-     * admin_init
261
-     */
262
-    public function admin_init()
263
-    {
264
-        EE_Registry::$i18n_js_strings = array_merge(
265
-            EE_Registry::$i18n_js_strings,
266
-            array(
267
-                'image_confirm'          => esc_html__(
268
-                    'Do you really want to delete this image? Please remember to update your event to complete the removal.',
269
-                    'event_espresso'
270
-                ),
271
-                'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
272
-                'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
273
-                'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
274
-                'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
275
-                'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
276
-            )
277
-        );
278
-    }
279
-
280
-
281
-    /**
282
-     * Add per page screen options to the default ticket list table view.
283
-     *
284
-     * @throws InvalidArgumentException
285
-     * @throws InvalidDataTypeException
286
-     * @throws InvalidInterfaceException
287
-     */
288
-    protected function _add_screen_options_ticket_list_table()
289
-    {
290
-        $this->_per_page_screen_option();
291
-    }
292
-
293
-
294
-    /**
295
-     * @param string $return
296
-     * @param int    $id
297
-     * @param string $new_title
298
-     * @param string $new_slug
299
-     * @return string
300
-     */
301
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
302
-    {
303
-        $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
304
-        // make sure this is only when editing
305
-        if (! empty($id)) {
306
-            $href = EE_Admin_Page::add_query_args_and_nonce(
307
-                array('action' => 'duplicate_event', 'EVT_ID' => $id),
308
-                $this->_admin_base_url
309
-            );
310
-            $title = esc_attr__('Duplicate Event', 'event_espresso');
311
-            $return .= '<a href="'
312
-                       . $href
313
-                       . '" title="'
314
-                       . $title
315
-                       . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
316
-                       . $title
317
-                       . '</a>';
318
-        }
319
-        return $return;
320
-    }
321
-
322
-
323
-    /**
324
-     * Set the list table views for the default ticket list table view.
325
-     */
326
-    public function _set_list_table_views_ticket_list_table()
327
-    {
328
-        $this->_views = array(
329
-            'all'     => array(
330
-                'slug'        => 'all',
331
-                'label'       => esc_html__('All', 'event_espresso'),
332
-                'count'       => 0,
333
-                'bulk_action' => array(
334
-                    'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
335
-                ),
336
-            ),
337
-            'trashed' => array(
338
-                'slug'        => 'trashed',
339
-                'label'       => esc_html__('Trash', 'event_espresso'),
340
-                'count'       => 0,
341
-                'bulk_action' => array(
342
-                    'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
343
-                    'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
344
-                ),
345
-            ),
346
-        );
347
-    }
348
-
349
-
350
-    /**
351
-     * Enqueue scripts and styles for the event editor.
352
-     */
353
-    public function load_scripts_styles_edit()
354
-    {
355
-        if (! $this->admin_config->useAdvancedEditor()) {
356
-            wp_register_script(
357
-                'ee-event-editor-heartbeat',
358
-                EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
359
-                ['ee_admin_js', 'heartbeat'],
360
-                EVENT_ESPRESSO_VERSION,
361
-                true
362
-            );
363
-            wp_enqueue_script('ee-accounting');
364
-            wp_enqueue_script('ee-event-editor-heartbeat');
365
-        }
366
-        wp_enqueue_script('event_editor_js');
367
-        // styles
368
-        wp_enqueue_style('espresso-ui-theme');
369
-    }
370
-
371
-
372
-    /**
373
-     * Returns template for the additional datetime.
374
-     *
375
-     * @param $template
376
-     * @param $template_args
377
-     * @return mixed
378
-     * @throws DomainException
379
-     */
380
-    public function add_additional_datetime_button($template, $template_args)
381
-    {
382
-        return EEH_Template::display_template(
383
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
384
-            $template_args,
385
-            true
386
-        );
387
-    }
388
-
389
-
390
-    /**
391
-     * Returns the template for cloning a datetime.
392
-     *
393
-     * @param $template
394
-     * @param $template_args
395
-     * @return mixed
396
-     * @throws DomainException
397
-     */
398
-    public function add_datetime_clone_button($template, $template_args)
399
-    {
400
-        return EEH_Template::display_template(
401
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
402
-            $template_args,
403
-            true
404
-        );
405
-    }
406
-
407
-
408
-    /**
409
-     * Returns the template for datetime timezones.
410
-     *
411
-     * @param $template
412
-     * @param $template_args
413
-     * @return mixed
414
-     * @throws DomainException
415
-     */
416
-    public function datetime_timezones_template($template, $template_args)
417
-    {
418
-        return EEH_Template::display_template(
419
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
420
-            $template_args,
421
-            true
422
-        );
423
-    }
424
-
425
-
426
-    /**
427
-     * Sets the views for the default list table view.
428
-     *
429
-     * @throws EE_Error
430
-     */
431
-    protected function _set_list_table_views_default()
432
-    {
433
-        parent::_set_list_table_views_default();
434
-        $new_views = array(
435
-            'today' => array(
436
-                'slug'        => 'today',
437
-                'label'       => esc_html__('Today', 'event_espresso'),
438
-                'count'       => $this->total_events_today(),
439
-                'bulk_action' => array(
440
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
441
-                ),
442
-            ),
443
-            'month' => array(
444
-                'slug'        => 'month',
445
-                'label'       => esc_html__('This Month', 'event_espresso'),
446
-                'count'       => $this->total_events_this_month(),
447
-                'bulk_action' => array(
448
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
449
-                ),
450
-            ),
451
-        );
452
-        $this->_views = array_merge($this->_views, $new_views);
453
-    }
454
-
455
-
456
-    /**
457
-     * Returns the extra action links for the default list table view.
458
-     *
459
-     * @param array    $action_links
460
-     * @param EE_Event $event
461
-     * @return array
462
-     * @throws EE_Error
463
-     * @throws InvalidArgumentException
464
-     * @throws InvalidDataTypeException
465
-     * @throws InvalidInterfaceException
466
-     * @throws ReflectionException
467
-     */
468
-    public function extra_list_table_actions(array $action_links, EE_Event $event)
469
-    {
470
-        if (EE_Registry::instance()->CAP->current_user_can(
471
-            'ee_read_registrations',
472
-            'espresso_registrations_reports',
473
-            $event->ID()
474
-        )
475
-        ) {
476
-            $reports_query_args = array(
477
-                'action' => 'reports',
478
-                'EVT_ID' => $event->ID(),
479
-            );
480
-            $reports_link = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
481
-            $action_links[] = '<a href="'
482
-                              . $reports_link
483
-                              . '" title="'
484
-                              . esc_attr__('View Report', 'event_espresso')
485
-                              . '"><div class="dashicons dashicons-chart-bar"></div></a>'
486
-                              . "\n\t";
487
-        }
488
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
489
-            EE_Registry::instance()->load_helper('MSG_Template');
490
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
491
-                'see_notifications_for',
492
-                null,
493
-                array('EVT_ID' => $event->ID())
494
-            );
495
-        }
496
-        return $action_links;
497
-    }
498
-
499
-
500
-    /**
501
-     * @param $items
502
-     * @return mixed
503
-     */
504
-    public function additional_legend_items($items)
505
-    {
506
-        if (EE_Registry::instance()->CAP->current_user_can(
507
-            'ee_read_registrations',
508
-            'espresso_registrations_reports'
509
-        )
510
-        ) {
511
-            $items['reports'] = array(
512
-                'class' => 'dashicons dashicons-chart-bar',
513
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
514
-            );
515
-        }
516
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
517
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
518
-            // $related_for_icon can sometimes be a string so 'css_class' would be an illegal offset
519
-            // (can only use numeric offsets when treating strings as arrays)
520
-            if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
521
-                $items['view_related_messages'] = array(
522
-                    'class' => $related_for_icon['css_class'],
523
-                    'desc'  => $related_for_icon['label'],
524
-                );
525
-            }
526
-        }
527
-        return $items;
528
-    }
529
-
530
-
531
-    /**
532
-     * This is the callback method for the duplicate event route
533
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
534
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
535
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
536
-     * After duplication the redirect is to the new event edit page.
537
-     *
538
-     * @return void
539
-     * @throws EE_Error If EE_Event is not available with given ID
540
-     * @throws InvalidArgumentException
541
-     * @throws InvalidDataTypeException
542
-     * @throws InvalidInterfaceException
543
-     * @throws ReflectionException
544
-     * @access protected
545
-     */
546
-    protected function _duplicate_event()
547
-    {
548
-        // first make sure the ID for the event is in the request.
549
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
550
-        if (! isset($this->_req_data['EVT_ID'])) {
551
-            EE_Error::add_error(
552
-                esc_html__(
553
-                    'In order to duplicate an event an Event ID is required.  None was given.',
554
-                    'event_espresso'
555
-                ),
556
-                __FILE__,
557
-                __FUNCTION__,
558
-                __LINE__
559
-            );
560
-            $this->_redirect_after_action(false, '', '', array(), true);
561
-            return;
562
-        }
563
-        // k we've got EVT_ID so let's use that to get the event we'll duplicate
564
-        $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
565
-        if (! $orig_event instanceof EE_Event) {
566
-            throw new EE_Error(
567
-                sprintf(
568
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
569
-                    $this->_req_data['EVT_ID']
570
-                )
571
-            );
572
-        }
573
-        // k now let's clone the $orig_event before getting relations
574
-        $new_event = clone $orig_event;
575
-        // original datetimes
576
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
577
-        // other original relations
578
-        $orig_ven = $orig_event->get_many_related('Venue');
579
-        // reset the ID and modify other details to make it clear this is a dupe
580
-        $new_event->set('EVT_ID', 0);
581
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
582
-        $new_event->set('EVT_name', $new_name);
583
-        $new_event->set(
584
-            'EVT_slug',
585
-            wp_unique_post_slug(
586
-                sanitize_title($orig_event->name()),
587
-                0,
588
-                'publish',
589
-                'espresso_events',
590
-                0
591
-            )
592
-        );
593
-        $new_event->set('status', 'draft');
594
-        // duplicate discussion settings
595
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
596
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
597
-        // save the new event
598
-        $new_event->save();
599
-        // venues
600
-        foreach ($orig_ven as $ven) {
601
-            $new_event->_add_relation_to($ven, 'Venue');
602
-        }
603
-        $new_event->save();
604
-        // now we need to get the question group relations and handle that
605
-        // first primary question groups
606
-        $orig_primary_qgs = $orig_event->get_many_related(
607
-            'Question_Group',
608
-            [['Event_Question_Group.EQG_primary' => true]]
609
-        );
610
-        if (! empty($orig_primary_qgs)) {
611
-            foreach ($orig_primary_qgs as $id => $obj) {
612
-                if ($obj instanceof EE_Question_Group) {
613
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
614
-                }
615
-            }
616
-        }
617
-        // next additional attendee question groups
618
-        $orig_additional_qgs = $orig_event->get_many_related(
619
-            'Question_Group',
620
-            [['Event_Question_Group.EQG_additional' => true]]
621
-        );
622
-        if (! empty($orig_additional_qgs)) {
623
-            foreach ($orig_additional_qgs as $id => $obj) {
624
-                if ($obj instanceof EE_Question_Group) {
625
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
626
-                }
627
-            }
628
-        }
629
-
630
-        $new_event->save();
631
-
632
-        // k now that we have the new event saved we can loop through the datetimes and start adding relations.
633
-        $cloned_tickets = array();
634
-        foreach ($orig_datetimes as $orig_dtt) {
635
-            if (! $orig_dtt instanceof EE_Datetime) {
636
-                continue;
637
-            }
638
-            $new_dtt = clone $orig_dtt;
639
-            $orig_tkts = $orig_dtt->tickets();
640
-            // save new dtt then add to event
641
-            $new_dtt->set('DTT_ID', 0);
642
-            $new_dtt->set('DTT_sold', 0);
643
-            $new_dtt->set_reserved(0);
644
-            $new_dtt->save();
645
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
646
-            $new_event->save();
647
-            // now let's get the ticket relations setup.
648
-            foreach ((array) $orig_tkts as $orig_tkt) {
649
-                // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
650
-                if (! $orig_tkt instanceof EE_Ticket) {
651
-                    continue;
652
-                }
653
-                // is this ticket archived?  If it is then let's skip
654
-                if ($orig_tkt->get('TKT_deleted')) {
655
-                    continue;
656
-                }
657
-                // does this original ticket already exist in the clone_tickets cache?
658
-                //  If so we'll just use the new ticket from it.
659
-                if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
660
-                    $new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
661
-                } else {
662
-                    $new_tkt = clone $orig_tkt;
663
-                    // get relations on the $orig_tkt that we need to setup.
664
-                    $orig_prices = $orig_tkt->prices();
665
-                    $new_tkt->set('TKT_ID', 0);
666
-                    $new_tkt->set('TKT_sold', 0);
667
-                    $new_tkt->set('TKT_reserved', 0);
668
-                    $new_tkt->save(); // make sure new ticket has ID.
669
-                    // price relations on new ticket need to be setup.
670
-                    foreach ($orig_prices as $orig_price) {
671
-                        $new_price = clone $orig_price;
672
-                        $new_price->set('PRC_ID', 0);
673
-                        $new_price->save();
674
-                        $new_tkt->_add_relation_to($new_price, 'Price');
675
-                        $new_tkt->save();
676
-                    }
677
-
678
-                    do_action(
679
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
680
-                        $orig_tkt,
681
-                        $new_tkt,
682
-                        $orig_prices,
683
-                        $orig_event,
684
-                        $orig_dtt,
685
-                        $new_dtt
686
-                    );
687
-                }
688
-                // k now we can add the new ticket as a relation to the new datetime
689
-                // and make sure its added to our cached $cloned_tickets array
690
-                // for use with later datetimes that have the same ticket.
691
-                $new_dtt->_add_relation_to($new_tkt, 'Ticket');
692
-                $new_dtt->save();
693
-                $cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
694
-            }
695
-        }
696
-        // clone taxonomy information
697
-        $taxonomies_to_clone_with = apply_filters(
698
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
699
-            array('espresso_event_categories', 'espresso_event_type', 'post_tag')
700
-        );
701
-        // get terms for original event (notice)
702
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
703
-        // loop through terms and add them to new event.
704
-        foreach ($orig_terms as $term) {
705
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
706
-        }
707
-
708
-        // duplicate other core WP_Post items for this event.
709
-        // post thumbnail (feature image).
710
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
711
-        if ($feature_image_id) {
712
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
713
-        }
714
-
715
-        // duplicate page_template setting
716
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
717
-        if ($page_template) {
718
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
719
-        }
720
-
721
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
722
-        // now let's redirect to the edit page for this duplicated event if we have a new event id.
723
-        if ($new_event->ID()) {
724
-            $redirect_args = array(
725
-                'post'   => $new_event->ID(),
726
-                'action' => 'edit',
727
-            );
728
-            EE_Error::add_success(
729
-                esc_html__(
730
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
731
-                    'event_espresso'
732
-                )
733
-            );
734
-        } else {
735
-            $redirect_args = array(
736
-                'action' => 'default',
737
-            );
738
-            EE_Error::add_error(
739
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
740
-                __FILE__,
741
-                __FUNCTION__,
742
-                __LINE__
743
-            );
744
-        }
745
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
746
-    }
747
-
748
-
749
-    /**
750
-     * Generates output for the import page.
751
-     *
752
-     * @throws DomainException
753
-     * @throws EE_Error
754
-     * @throws InvalidArgumentException
755
-     * @throws InvalidDataTypeException
756
-     * @throws InvalidInterfaceException
757
-     */
758
-    protected function _import_page()
759
-    {
760
-        $title = esc_html__('Import', 'event_espresso');
761
-        $intro = esc_html__(
762
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
763
-            'event_espresso'
764
-        );
765
-        $form_url = EVENTS_ADMIN_URL;
766
-        $action = 'import_events';
767
-        $type = 'csv';
768
-        $this->_template_args['form'] = EE_Import::instance()->upload_form(
769
-            $title,
770
-            $intro,
771
-            $form_url,
772
-            $action,
773
-            $type
774
-        );
775
-        $this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
776
-            array('action' => 'sample_export_file'),
777
-            $this->_admin_base_url
778
-        );
779
-        $content = EEH_Template::display_template(
780
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
781
-            $this->_template_args,
782
-            true
783
-        );
784
-        $this->_template_args['admin_page_content'] = $content;
785
-        $this->display_admin_page_with_sidebar();
786
-    }
787
-
788
-
789
-    /**
790
-     * _import_events
791
-     * This handles displaying the screen and running imports for importing events.
792
-     *
793
-     * @return void
794
-     * @throws EE_Error
795
-     * @throws InvalidArgumentException
796
-     * @throws InvalidDataTypeException
797
-     * @throws InvalidInterfaceException
798
-     */
799
-    protected function _import_events()
800
-    {
801
-        require_once(EE_CLASSES . 'EE_Import.class.php');
802
-        $success = EE_Import::instance()->import();
803
-        $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
804
-    }
805
-
806
-
807
-    /**
808
-     * _events_export
809
-     * Will export all (or just the given event) to a Excel compatible file.
810
-     *
811
-     * @access protected
812
-     * @return void
813
-     */
814
-    protected function _events_export()
815
-    {
816
-        if (isset($this->_req_data['EVT_ID'])) {
817
-            $event_ids = $this->_req_data['EVT_ID'];
818
-        } elseif (isset($this->_req_data['EVT_IDs'])) {
819
-            $event_ids = $this->_req_data['EVT_IDs'];
820
-        } else {
821
-            $event_ids = null;
822
-        }
823
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
824
-        $new_request_args = array(
825
-            'export' => 'report',
826
-            'action' => 'all_event_data',
827
-            'EVT_ID' => $event_ids,
828
-        );
829
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
830
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
831
-            require_once(EE_CLASSES . 'EE_Export.class.php');
832
-            $EE_Export = EE_Export::instance($this->_req_data);
833
-            if ($EE_Export instanceof EE_Export) {
834
-                $EE_Export->export();
835
-            }
836
-        }
837
-    }
838
-
839
-
840
-    /**
841
-     * handle category exports()
842
-     *
843
-     * @return void
844
-     */
845
-    protected function _categories_export()
846
-    {
847
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
848
-        $new_request_args = array(
849
-            'export'       => 'report',
850
-            'action'       => 'categories',
851
-            'category_ids' => $this->_req_data['EVT_CAT_ID'],
852
-        );
853
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
854
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
855
-            require_once(EE_CLASSES . 'EE_Export.class.php');
856
-            $EE_Export = EE_Export::instance($this->_req_data);
857
-            if ($EE_Export instanceof EE_Export) {
858
-                $EE_Export->export();
859
-            }
860
-        }
861
-    }
862
-
863
-
864
-    /**
865
-     * Creates a sample CSV file for importing
866
-     */
867
-    protected function _sample_export_file()
868
-    {
869
-        $EE_Export = EE_Export::instance();
870
-        if ($EE_Export instanceof EE_Export) {
871
-            $EE_Export->export();
872
-        }
873
-    }
874
-
875
-
876
-    /*************        Template Settings        *************/
877
-    /**
878
-     * Generates template settings page output
879
-     *
880
-     * @throws DomainException
881
-     * @throws EE_Error
882
-     * @throws InvalidArgumentException
883
-     * @throws InvalidDataTypeException
884
-     * @throws InvalidInterfaceException
885
-     */
886
-    protected function _template_settings()
887
-    {
888
-        $this->_template_args['values'] = $this->_yes_no_values;
889
-        /**
890
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
891
-         * from General_Settings_Admin_Page to here.
892
-         */
893
-        $this->_template_args = apply_filters(
894
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
895
-            $this->_template_args
896
-        );
897
-        $this->_set_add_edit_form_tags('update_template_settings');
898
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
899
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
900
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
901
-            $this->_template_args,
902
-            true
903
-        );
904
-        $this->display_admin_page_with_sidebar();
905
-    }
906
-
907
-
908
-    /**
909
-     * Handler for updating template settings.
910
-     *
911
-     * @throws EE_Error
912
-     * @throws InvalidArgumentException
913
-     * @throws InvalidDataTypeException
914
-     * @throws InvalidInterfaceException
915
-     */
916
-    protected function _update_template_settings()
917
-    {
918
-        /**
919
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
920
-         * from General_Settings_Admin_Page to here.
921
-         */
922
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
923
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
924
-            EE_Registry::instance()->CFG->template_settings,
925
-            $this->_req_data
926
-        );
927
-        // update custom post type slugs and detect if we need to flush rewrite rules
928
-        $old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
929
-        EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
930
-            ? EE_Registry::instance()->CFG->core->event_cpt_slug
931
-            : EEH_URL::slugify($this->_req_data['event_cpt_slug'], 'events');
932
-        $what = 'Template Settings';
933
-        $success = $this->_update_espresso_configuration(
934
-            $what,
935
-            EE_Registry::instance()->CFG->template_settings,
936
-            __FILE__,
937
-            __FUNCTION__,
938
-            __LINE__
939
-        );
940
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug !== $old_slug) {
941
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
942
-            $rewrite_rules = LoaderFactory::getLoader()->getShared(
943
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
944
-            );
945
-            $rewrite_rules->flush();
946
-        }
947
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
948
-    }
949
-
950
-
951
-    /**
952
-     * _premium_event_editor_meta_boxes
953
-     * add all metaboxes related to the event_editor
954
-     *
955
-     * @access protected
956
-     * @return void
957
-     * @throws EE_Error
958
-     * @throws InvalidArgumentException
959
-     * @throws InvalidDataTypeException
960
-     * @throws InvalidInterfaceException
961
-     * @throws ReflectionException
962
-     */
963
-    protected function _premium_event_editor_meta_boxes()
964
-    {
965
-        $this->verify_cpt_object();
966
-        add_meta_box(
967
-            'espresso_event_editor_event_options',
968
-            esc_html__('Event Registration Options', 'event_espresso'),
969
-            array($this, 'registration_options_meta_box'),
970
-            $this->page_slug,
971
-            'side',
972
-            'core'
973
-        );
974
-    }
975
-
976
-
977
-    /**
978
-     * override caf metabox
979
-     *
980
-     * @return void
981
-     * @throws DomainException
982
-     * @throws EE_Error
983
-     */
984
-    public function registration_options_meta_box()
985
-    {
986
-        $yes_no_values = array(
987
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
988
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
989
-        );
990
-        $default_reg_status_values = EEM_Registration::reg_status_array(
991
-            array(
992
-                EEM_Registration::status_id_cancelled,
993
-                EEM_Registration::status_id_declined,
994
-                EEM_Registration::status_id_incomplete,
995
-                EEM_Registration::status_id_wait_list,
996
-            ),
997
-            true
998
-        );
999
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1000
-        $template_args['_event'] = $this->_cpt_model_obj;
1001
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1002
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1003
-            'default_reg_status',
1004
-            $default_reg_status_values,
1005
-            $this->_cpt_model_obj->default_registration_status()
1006
-        );
1007
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1008
-            'display_desc',
1009
-            $yes_no_values,
1010
-            $this->_cpt_model_obj->display_description()
1011
-        );
1012
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1013
-            'display_ticket_selector',
1014
-            $yes_no_values,
1015
-            $this->_cpt_model_obj->display_ticket_selector(),
1016
-            '',
1017
-            '',
1018
-            false
1019
-        );
1020
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
1021
-            'EVT_default_registration_status',
1022
-            $default_reg_status_values,
1023
-            $this->_cpt_model_obj->default_registration_status()
1024
-        );
1025
-        $template_args['additional_registration_options'] = apply_filters(
1026
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1027
-            '',
1028
-            $template_args,
1029
-            $yes_no_values,
1030
-            $default_reg_status_values
1031
-        );
1032
-        EEH_Template::display_template(
1033
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
1034
-            $template_args
1035
-        );
1036
-    }
1037
-
1038
-
1039
-
1040
-    /**
1041
-     * wp_list_table_mods for caf
1042
-     * ============================
1043
-     */
1044
-    /**
1045
-     * hook into list table filters and provide filters for caffeinated list table
1046
-     *
1047
-     * @param array $old_filters    any existing filters present
1048
-     * @param array $list_table_obj the list table object
1049
-     * @return array                  new filters
1050
-     * @throws EE_Error
1051
-     * @throws InvalidArgumentException
1052
-     * @throws InvalidDataTypeException
1053
-     * @throws InvalidInterfaceException
1054
-     * @throws ReflectionException
1055
-     */
1056
-    public function list_table_filters($old_filters, $list_table_obj)
1057
-    {
1058
-        $filters = array();
1059
-        // first month/year filters
1060
-        $filters[] = $this->espresso_event_months_dropdown();
1061
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1062
-        // active status dropdown
1063
-        if ($status !== 'draft') {
1064
-            $filters[] = $this->active_status_dropdown(
1065
-                isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
1066
-            );
1067
-            $filters[] = $this->venuesDropdown(
1068
-                isset($this->_req_data['venue']) ? $this->_req_data['venue'] : ''
1069
-            );
1070
-        }
1071
-        // category filter
1072
-        $filters[] = $this->category_dropdown();
1073
-        return array_merge($old_filters, $filters);
1074
-    }
1075
-
1076
-
1077
-    /**
1078
-     * espresso_event_months_dropdown
1079
-     *
1080
-     * @access public
1081
-     * @return string                dropdown listing month/year selections for events.
1082
-     */
1083
-    public function espresso_event_months_dropdown()
1084
-    {
1085
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
1086
-        // Note we need to include any other filters that are set!
1087
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1088
-        // categories?
1089
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1090
-            ? $this->_req_data['EVT_CAT']
1091
-            : null;
1092
-        // active status?
1093
-        $active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
1094
-        $cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1095
-        return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1096
-    }
1097
-
1098
-
1099
-    /**
1100
-     * returns a list of "active" statuses on the event
1101
-     *
1102
-     * @param  string $current_value whatever the current active status is
1103
-     * @return string
1104
-     */
1105
-    public function active_status_dropdown($current_value = '')
1106
-    {
1107
-        $select_name = 'active_status';
1108
-        $values = array(
1109
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1110
-            'active'   => esc_html__('Active', 'event_espresso'),
1111
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1112
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1113
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1114
-        );
1115
-
1116
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1117
-    }
1118
-
1119
-
1120
-    /**
1121
-     * returns a list of "venues"
1122
-     *
1123
-     * @param string $current_value whatever the current active status is
1124
-     * @return string
1125
-     * @throws EE_Error
1126
-     * @throws InvalidArgumentException
1127
-     * @throws InvalidDataTypeException
1128
-     * @throws InvalidInterfaceException
1129
-     * @throws ReflectionException
1130
-     */
1131
-    protected function venuesDropdown($current_value = '')
1132
-    {
1133
-        $select_name = 'venue';
1134
-        $values = array(
1135
-            '' => esc_html__('All Venues', 'event_espresso'),
1136
-        );
1137
-        // populate the list of venues.
1138
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1139
-        $venues = $venue_model->get_all(array('order_by' => array('VNU_name' => 'ASC')));
1140
-
1141
-        foreach ($venues as $venue) {
1142
-            $values[ $venue->ID() ] = $venue->name();
1143
-        }
1144
-
1145
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1146
-    }
1147
-
1148
-
1149
-    /**
1150
-     * output a dropdown of the categories for the category filter on the event admin list table
1151
-     *
1152
-     * @access  public
1153
-     * @return string html
1154
-     */
1155
-    public function category_dropdown()
1156
-    {
1157
-        $cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1158
-        return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1159
-    }
1160
-
1161
-
1162
-    /**
1163
-     * get total number of events today
1164
-     *
1165
-     * @access public
1166
-     * @return int
1167
-     * @throws EE_Error
1168
-     * @throws InvalidArgumentException
1169
-     * @throws InvalidDataTypeException
1170
-     * @throws InvalidInterfaceException
1171
-     */
1172
-    public function total_events_today()
1173
-    {
1174
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1175
-            'DTT_EVT_start',
1176
-            date('Y-m-d') . ' 00:00:00',
1177
-            'Y-m-d H:i:s',
1178
-            'UTC'
1179
-        );
1180
-        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1181
-            'DTT_EVT_start',
1182
-            date('Y-m-d') . ' 23:59:59',
1183
-            'Y-m-d H:i:s',
1184
-            'UTC'
1185
-        );
1186
-        $where = array(
1187
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1188
-        );
1189
-        return EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1190
-    }
1191
-
1192
-
1193
-    /**
1194
-     * get total number of events this month
1195
-     *
1196
-     * @access public
1197
-     * @return int
1198
-     * @throws EE_Error
1199
-     * @throws InvalidArgumentException
1200
-     * @throws InvalidDataTypeException
1201
-     * @throws InvalidInterfaceException
1202
-     */
1203
-    public function total_events_this_month()
1204
-    {
1205
-        // Dates
1206
-        $this_year_r = date('Y');
1207
-        $this_month_r = date('m');
1208
-        $days_this_month = date('t');
1209
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1210
-            'DTT_EVT_start',
1211
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1212
-            'Y-m-d H:i:s',
1213
-            'UTC'
1214
-        );
1215
-        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1216
-            'DTT_EVT_start',
1217
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1218
-            'Y-m-d H:i:s',
1219
-            'UTC'
1220
-        );
1221
-        $where = array(
1222
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1223
-        );
1224
-        return EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1225
-    }
1226
-
1227
-
1228
-    /** DEFAULT TICKETS STUFF **/
1229
-
1230
-    /**
1231
-     * Output default tickets list table view.
1232
-     *
1233
-     * @throws DomainException
1234
-     * @throws EE_Error
1235
-     * @throws InvalidArgumentException
1236
-     * @throws InvalidDataTypeException
1237
-     * @throws InvalidInterfaceException
1238
-     */
1239
-    public function _tickets_overview_list_table()
1240
-    {
1241
-        $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1242
-        $this->display_admin_list_table_page_with_no_sidebar();
1243
-    }
1244
-
1245
-
1246
-    /**
1247
-     * @param int  $per_page
1248
-     * @param bool $count
1249
-     * @param bool $trashed
1250
-     * @return EE_Soft_Delete_Base_Class[]|int
1251
-     * @throws EE_Error
1252
-     * @throws InvalidArgumentException
1253
-     * @throws InvalidDataTypeException
1254
-     * @throws InvalidInterfaceException
1255
-     */
1256
-    public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1257
-    {
1258
-        $orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1259
-        $order = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1260
-        switch ($orderby) {
1261
-            case 'TKT_name':
1262
-                $orderby = array('TKT_name' => $order);
1263
-                break;
1264
-            case 'TKT_price':
1265
-                $orderby = array('TKT_price' => $order);
1266
-                break;
1267
-            case 'TKT_uses':
1268
-                $orderby = array('TKT_uses' => $order);
1269
-                break;
1270
-            case 'TKT_min':
1271
-                $orderby = array('TKT_min' => $order);
1272
-                break;
1273
-            case 'TKT_max':
1274
-                $orderby = array('TKT_max' => $order);
1275
-                break;
1276
-            case 'TKT_qty':
1277
-                $orderby = array('TKT_qty' => $order);
1278
-                break;
1279
-        }
1280
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1281
-            ? $this->_req_data['paged']
1282
-            : 1;
1283
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1284
-            ? $this->_req_data['perpage']
1285
-            : $per_page;
1286
-        $_where = array(
1287
-            'TKT_is_default' => 1,
1288
-            'TKT_deleted'    => $trashed,
1289
-        );
1290
-        $offset = ($current_page - 1) * $per_page;
1291
-        $limit = array($offset, $per_page);
1292
-        if (isset($this->_req_data['s'])) {
1293
-            $sstr = '%' . $this->_req_data['s'] . '%';
1294
-            $_where['OR'] = array(
1295
-                'TKT_name'        => array('LIKE', $sstr),
1296
-                'TKT_description' => array('LIKE', $sstr),
1297
-            );
1298
-        }
1299
-        $query_params = array(
1300
-            $_where,
1301
-            'order_by' => $orderby,
1302
-            'limit'    => $limit,
1303
-            'group_by' => 'TKT_ID',
1304
-        );
1305
-        if ($count) {
1306
-            return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1307
-        }
1308
-        return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1309
-    }
1310
-
1311
-
1312
-    /**
1313
-     * @param bool $trash
1314
-     * @throws EE_Error
1315
-     * @throws InvalidArgumentException
1316
-     * @throws InvalidDataTypeException
1317
-     * @throws InvalidInterfaceException
1318
-     */
1319
-    protected function _trash_or_restore_ticket($trash = false)
1320
-    {
1321
-        $success = 1;
1322
-        $TKT = EEM_Ticket::instance();
1323
-        // checkboxes?
1324
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1325
-            // if array has more than one element then success message should be plural
1326
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1327
-            // cycle thru the boxes
1328
-            foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1329
-                if ($trash) {
1330
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1331
-                        $success = 0;
1332
-                    }
1333
-                } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1334
-                    $success = 0;
1335
-                }
1336
-            }
1337
-        } else {
1338
-            // grab single id and trash
1339
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1340
-            if ($trash) {
1341
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1342
-                    $success = 0;
1343
-                }
1344
-            } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1345
-                $success = 0;
1346
-            }
1347
-        }
1348
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1349
-        $query_args = array(
1350
-            'action' => 'ticket_list_table',
1351
-            'status' => $trash ? '' : 'trashed',
1352
-        );
1353
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1354
-    }
1355
-
1356
-
1357
-    /**
1358
-     * Handles trashing default ticket.
1359
-     *
1360
-     * @throws EE_Error
1361
-     * @throws InvalidArgumentException
1362
-     * @throws InvalidDataTypeException
1363
-     * @throws InvalidInterfaceException
1364
-     * @throws ReflectionException
1365
-     */
1366
-    protected function _delete_ticket()
1367
-    {
1368
-        $success = 1;
1369
-        // checkboxes?
1370
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1371
-            // if array has more than one element then success message should be plural
1372
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1373
-            // cycle thru the boxes
1374
-            foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1375
-                // delete
1376
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1377
-                    $success = 0;
1378
-                }
1379
-            }
1380
-        } else {
1381
-            // grab single id and trash
1382
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1383
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1384
-                $success = 0;
1385
-            }
1386
-        }
1387
-        $action_desc = 'deleted';
1388
-        // fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1389
-        $ticket_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
1390
-            [['TKT_is_default' => 1]],
1391
-            'TKT_ID',
1392
-            true
1393
-        );
1394
-        $query_args = $ticket_count
1395
-            ? []
1396
-            : [
1397
-                'action' => 'ticket_list_table',
1398
-                'status' => 'trashed'
1399
-            ];
1400
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1401
-    }
1402
-
1403
-
1404
-    /**
1405
-     * @param int $TKT_ID
1406
-     * @return bool|int
1407
-     * @throws EE_Error
1408
-     * @throws InvalidArgumentException
1409
-     * @throws InvalidDataTypeException
1410
-     * @throws InvalidInterfaceException
1411
-     * @throws ReflectionException
1412
-     */
1413
-    protected function _delete_the_ticket($TKT_ID)
1414
-    {
1415
-        $ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1416
-        if (! $ticket instanceof EE_Ticket) {
1417
-            return false;
1418
-        }
1419
-        $ticket->_remove_relations('Datetime');
1420
-        // delete all related prices first
1421
-        $ticket->delete_related_permanently('Price');
1422
-        return $ticket->delete_permanently();
1423
-    }
19
+	/**
20
+	 * @var EE_Admin_Config
21
+	 */
22
+	protected $admin_config;
23
+
24
+	/**
25
+	 * @var AdvancedEditorAdminFormSection
26
+	 */
27
+	protected $advanced_editor_admin_form;
28
+
29
+
30
+	/**
31
+	 * Extend_Events_Admin_Page constructor.
32
+	 *
33
+	 * @param bool $routing
34
+	 * @throws ReflectionException
35
+	 */
36
+	public function __construct($routing = true)
37
+	{
38
+		if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
39
+			define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
40
+			define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
41
+			define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
42
+		}
43
+		parent::__construct($routing);
44
+		$this->admin_config = $this->loader->getShared('EE_Admin_Config');
45
+	}
46
+
47
+
48
+	/**
49
+	 * Sets routes.
50
+	 *
51
+	 * @throws EE_Error
52
+	 * @throws InvalidArgumentException
53
+	 * @throws InvalidDataTypeException
54
+	 * @throws InvalidInterfaceException
55
+	 * @throws Exception
56
+	 */
57
+	protected function _extend_page_config()
58
+	{
59
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
60
+		// is there a evt_id in the request?
61
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
62
+			? $this->_req_data['EVT_ID']
63
+			: 0;
64
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
65
+		// tkt_id?
66
+		$tkt_id = ! empty($this->_req_data['TKT_ID']) && ! is_array($this->_req_data['TKT_ID'])
67
+			? $this->_req_data['TKT_ID']
68
+			: 0;
69
+		$new_page_routes = array(
70
+			'duplicate_event'          => array(
71
+				'func'       => '_duplicate_event',
72
+				'capability' => 'ee_edit_event',
73
+				'obj_id'     => $evt_id,
74
+				'noheader'   => true,
75
+			),
76
+			'import_page'              => array(
77
+				'func'       => '_import_page',
78
+				'capability' => 'import',
79
+			),
80
+			'import'                   => array(
81
+				'func'       => '_import_events',
82
+				'capability' => 'import',
83
+				'noheader'   => true,
84
+			),
85
+			'import_events'            => array(
86
+				'func'       => '_import_events',
87
+				'capability' => 'import',
88
+				'noheader'   => true,
89
+			),
90
+			'export_events'            => array(
91
+				'func'       => '_events_export',
92
+				'capability' => 'export',
93
+				'noheader'   => true,
94
+			),
95
+			'export_categories'        => array(
96
+				'func'       => '_categories_export',
97
+				'capability' => 'export',
98
+				'noheader'   => true,
99
+			),
100
+			'sample_export_file'       => array(
101
+				'func'       => '_sample_export_file',
102
+				'capability' => 'export',
103
+				'noheader'   => true,
104
+			),
105
+			'update_template_settings' => array(
106
+				'func'       => '_update_template_settings',
107
+				'capability' => 'manage_options',
108
+				'noheader'   => true,
109
+			),
110
+		);        // don't load these meta boxes if using the advanced editor
111
+		if (! $this->admin_config->useAdvancedEditor()) {
112
+			$this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
113
+			$this->_page_config['edit']['metaboxes'][] = '_premium_event_editor_meta_boxes';
114
+			$this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
115
+			$this->_page_config['edit']['qtips'][] = 'EE_Event_Editor_Tips';
116
+
117
+			$legacy_editor_page_routes = [
118
+				'ticket_list_table' => [
119
+					'func'       => '_tickets_overview_list_table',
120
+					'capability' => 'ee_read_default_tickets',
121
+				],
122
+				'trash_ticket'      => [
123
+					'func'       => '_trash_or_restore_ticket',
124
+					'capability' => 'ee_delete_default_ticket',
125
+					'obj_id'     => $tkt_id,
126
+					'noheader'   => true,
127
+					'args'       => ['trash' => true],
128
+				],
129
+				'trash_tickets'     => [
130
+					'func'       => '_trash_or_restore_ticket',
131
+					'capability' => 'ee_delete_default_tickets',
132
+					'noheader'   => true,
133
+					'args'       => ['trash' => true],
134
+				],
135
+				'restore_ticket'    => [
136
+					'func'       => '_trash_or_restore_ticket',
137
+					'capability' => 'ee_delete_default_ticket',
138
+					'obj_id'     => $tkt_id,
139
+					'noheader'   => true,
140
+				],
141
+				'restore_tickets'   => [
142
+					'func'       => '_trash_or_restore_ticket',
143
+					'capability' => 'ee_delete_default_tickets',
144
+					'noheader'   => true,
145
+				],
146
+				'delete_ticket'     => [
147
+					'func'       => '_delete_ticket',
148
+					'capability' => 'ee_delete_default_ticket',
149
+					'obj_id'     => $tkt_id,
150
+					'noheader'   => true,
151
+				],
152
+				'delete_tickets'    => [
153
+					'func'       => '_delete_ticket',
154
+					'capability' => 'ee_delete_default_tickets',
155
+					'noheader'   => true,
156
+				],
157
+			];
158
+			$new_page_routes = array_merge($new_page_routes, $legacy_editor_page_routes);
159
+		}
160
+
161
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
162
+		// partial route/config override
163
+		$this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
164
+		$this->_page_config['default']['list_table'] = 'Extend_Events_Admin_List_Table';
165
+		// add tickets tab but only if there are more than one default ticket!
166
+		$tkt_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
167
+			array(array('TKT_is_default' => 1)),
168
+			'TKT_ID',
169
+			true
170
+		);
171
+		if ($tkt_count > 1) {
172
+			$new_page_config = array(
173
+				'ticket_list_table' => array(
174
+					'nav'           => array(
175
+						'label' => esc_html__('Default Tickets', 'event_espresso'),
176
+						'order' => 60,
177
+					),
178
+					'list_table'    => 'Tickets_List_Table',
179
+					'require_nonce' => false,
180
+				),
181
+			);
182
+		}
183
+		// template settings
184
+		$new_page_config['template_settings'] = array(
185
+			'nav'           => array(
186
+				'label' => esc_html__('Templates', 'event_espresso'),
187
+				'order' => 30,
188
+			),
189
+			'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
190
+			'help_tabs'     => array(
191
+				'general_settings_templates_help_tab' => array(
192
+					'title'    => esc_html__('Templates', 'event_espresso'),
193
+					'filename' => 'general_settings_templates',
194
+				),
195
+			),
196
+			'help_tour'     => array('Templates_Help_Tour'),
197
+			'require_nonce' => false,
198
+		);
199
+		$this->_page_config = array_merge($this->_page_config, $new_page_config);
200
+		// add filters and actions
201
+		// modifying _views
202
+		add_filter(
203
+			'FHEE_event_datetime_metabox_add_additional_date_time_template',
204
+			array($this, 'add_additional_datetime_button'),
205
+			10,
206
+			2
207
+		);
208
+		add_filter(
209
+			'FHEE_event_datetime_metabox_clone_button_template',
210
+			array($this, 'add_datetime_clone_button'),
211
+			10,
212
+			2
213
+		);
214
+		add_filter(
215
+			'FHEE_event_datetime_metabox_timezones_template',
216
+			array($this, 'datetime_timezones_template'),
217
+			10,
218
+			2
219
+		);
220
+		// filters for event list table
221
+		add_filter('FHEE__Extend_Events_Admin_List_Table__filters', array($this, 'list_table_filters'), 10, 2);
222
+		add_filter(
223
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
224
+			array($this, 'extra_list_table_actions'),
225
+			10,
226
+			2
227
+		);
228
+		// legend item
229
+		add_filter('FHEE__Events_Admin_Page___event_legend_items__items', array($this, 'additional_legend_items'));
230
+		add_action('admin_init', array($this, 'admin_init'));
231
+	   // load additional handlers
232
+		$this->handleActionRequest();
233
+	}
234
+
235
+
236
+	private function getRequestAction()
237
+	{
238
+		return isset($this->_req_data['action']) ? sanitize_key($this->_req_data['action']) : null;
239
+	}
240
+
241
+
242
+	/**
243
+	 * @throws Exception
244
+	 */
245
+	private function handleActionRequest()
246
+	{
247
+		$action = $this->getRequestAction();
248
+		if ($action) {
249
+			// setup Advanced Editor ???
250
+			if ($action === 'default_event_settings' || $action === 'update_default_event_settings') {
251
+				$this->advanced_editor_admin_form = $this->loader->getShared(
252
+					'EventEspresso\core\domain\services\admin\events\default_settings\AdvancedEditorAdminFormSection'
253
+				);
254
+			}
255
+		}
256
+	}
257
+
258
+
259
+	/**
260
+	 * admin_init
261
+	 */
262
+	public function admin_init()
263
+	{
264
+		EE_Registry::$i18n_js_strings = array_merge(
265
+			EE_Registry::$i18n_js_strings,
266
+			array(
267
+				'image_confirm'          => esc_html__(
268
+					'Do you really want to delete this image? Please remember to update your event to complete the removal.',
269
+					'event_espresso'
270
+				),
271
+				'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
272
+				'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
273
+				'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
274
+				'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
275
+				'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
276
+			)
277
+		);
278
+	}
279
+
280
+
281
+	/**
282
+	 * Add per page screen options to the default ticket list table view.
283
+	 *
284
+	 * @throws InvalidArgumentException
285
+	 * @throws InvalidDataTypeException
286
+	 * @throws InvalidInterfaceException
287
+	 */
288
+	protected function _add_screen_options_ticket_list_table()
289
+	{
290
+		$this->_per_page_screen_option();
291
+	}
292
+
293
+
294
+	/**
295
+	 * @param string $return
296
+	 * @param int    $id
297
+	 * @param string $new_title
298
+	 * @param string $new_slug
299
+	 * @return string
300
+	 */
301
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
302
+	{
303
+		$return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
304
+		// make sure this is only when editing
305
+		if (! empty($id)) {
306
+			$href = EE_Admin_Page::add_query_args_and_nonce(
307
+				array('action' => 'duplicate_event', 'EVT_ID' => $id),
308
+				$this->_admin_base_url
309
+			);
310
+			$title = esc_attr__('Duplicate Event', 'event_espresso');
311
+			$return .= '<a href="'
312
+					   . $href
313
+					   . '" title="'
314
+					   . $title
315
+					   . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
316
+					   . $title
317
+					   . '</a>';
318
+		}
319
+		return $return;
320
+	}
321
+
322
+
323
+	/**
324
+	 * Set the list table views for the default ticket list table view.
325
+	 */
326
+	public function _set_list_table_views_ticket_list_table()
327
+	{
328
+		$this->_views = array(
329
+			'all'     => array(
330
+				'slug'        => 'all',
331
+				'label'       => esc_html__('All', 'event_espresso'),
332
+				'count'       => 0,
333
+				'bulk_action' => array(
334
+					'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
335
+				),
336
+			),
337
+			'trashed' => array(
338
+				'slug'        => 'trashed',
339
+				'label'       => esc_html__('Trash', 'event_espresso'),
340
+				'count'       => 0,
341
+				'bulk_action' => array(
342
+					'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
343
+					'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
344
+				),
345
+			),
346
+		);
347
+	}
348
+
349
+
350
+	/**
351
+	 * Enqueue scripts and styles for the event editor.
352
+	 */
353
+	public function load_scripts_styles_edit()
354
+	{
355
+		if (! $this->admin_config->useAdvancedEditor()) {
356
+			wp_register_script(
357
+				'ee-event-editor-heartbeat',
358
+				EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
359
+				['ee_admin_js', 'heartbeat'],
360
+				EVENT_ESPRESSO_VERSION,
361
+				true
362
+			);
363
+			wp_enqueue_script('ee-accounting');
364
+			wp_enqueue_script('ee-event-editor-heartbeat');
365
+		}
366
+		wp_enqueue_script('event_editor_js');
367
+		// styles
368
+		wp_enqueue_style('espresso-ui-theme');
369
+	}
370
+
371
+
372
+	/**
373
+	 * Returns template for the additional datetime.
374
+	 *
375
+	 * @param $template
376
+	 * @param $template_args
377
+	 * @return mixed
378
+	 * @throws DomainException
379
+	 */
380
+	public function add_additional_datetime_button($template, $template_args)
381
+	{
382
+		return EEH_Template::display_template(
383
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
384
+			$template_args,
385
+			true
386
+		);
387
+	}
388
+
389
+
390
+	/**
391
+	 * Returns the template for cloning a datetime.
392
+	 *
393
+	 * @param $template
394
+	 * @param $template_args
395
+	 * @return mixed
396
+	 * @throws DomainException
397
+	 */
398
+	public function add_datetime_clone_button($template, $template_args)
399
+	{
400
+		return EEH_Template::display_template(
401
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
402
+			$template_args,
403
+			true
404
+		);
405
+	}
406
+
407
+
408
+	/**
409
+	 * Returns the template for datetime timezones.
410
+	 *
411
+	 * @param $template
412
+	 * @param $template_args
413
+	 * @return mixed
414
+	 * @throws DomainException
415
+	 */
416
+	public function datetime_timezones_template($template, $template_args)
417
+	{
418
+		return EEH_Template::display_template(
419
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
420
+			$template_args,
421
+			true
422
+		);
423
+	}
424
+
425
+
426
+	/**
427
+	 * Sets the views for the default list table view.
428
+	 *
429
+	 * @throws EE_Error
430
+	 */
431
+	protected function _set_list_table_views_default()
432
+	{
433
+		parent::_set_list_table_views_default();
434
+		$new_views = array(
435
+			'today' => array(
436
+				'slug'        => 'today',
437
+				'label'       => esc_html__('Today', 'event_espresso'),
438
+				'count'       => $this->total_events_today(),
439
+				'bulk_action' => array(
440
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
441
+				),
442
+			),
443
+			'month' => array(
444
+				'slug'        => 'month',
445
+				'label'       => esc_html__('This Month', 'event_espresso'),
446
+				'count'       => $this->total_events_this_month(),
447
+				'bulk_action' => array(
448
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
449
+				),
450
+			),
451
+		);
452
+		$this->_views = array_merge($this->_views, $new_views);
453
+	}
454
+
455
+
456
+	/**
457
+	 * Returns the extra action links for the default list table view.
458
+	 *
459
+	 * @param array    $action_links
460
+	 * @param EE_Event $event
461
+	 * @return array
462
+	 * @throws EE_Error
463
+	 * @throws InvalidArgumentException
464
+	 * @throws InvalidDataTypeException
465
+	 * @throws InvalidInterfaceException
466
+	 * @throws ReflectionException
467
+	 */
468
+	public function extra_list_table_actions(array $action_links, EE_Event $event)
469
+	{
470
+		if (EE_Registry::instance()->CAP->current_user_can(
471
+			'ee_read_registrations',
472
+			'espresso_registrations_reports',
473
+			$event->ID()
474
+		)
475
+		) {
476
+			$reports_query_args = array(
477
+				'action' => 'reports',
478
+				'EVT_ID' => $event->ID(),
479
+			);
480
+			$reports_link = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
481
+			$action_links[] = '<a href="'
482
+							  . $reports_link
483
+							  . '" title="'
484
+							  . esc_attr__('View Report', 'event_espresso')
485
+							  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
486
+							  . "\n\t";
487
+		}
488
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
489
+			EE_Registry::instance()->load_helper('MSG_Template');
490
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
491
+				'see_notifications_for',
492
+				null,
493
+				array('EVT_ID' => $event->ID())
494
+			);
495
+		}
496
+		return $action_links;
497
+	}
498
+
499
+
500
+	/**
501
+	 * @param $items
502
+	 * @return mixed
503
+	 */
504
+	public function additional_legend_items($items)
505
+	{
506
+		if (EE_Registry::instance()->CAP->current_user_can(
507
+			'ee_read_registrations',
508
+			'espresso_registrations_reports'
509
+		)
510
+		) {
511
+			$items['reports'] = array(
512
+				'class' => 'dashicons dashicons-chart-bar',
513
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
514
+			);
515
+		}
516
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
517
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
518
+			// $related_for_icon can sometimes be a string so 'css_class' would be an illegal offset
519
+			// (can only use numeric offsets when treating strings as arrays)
520
+			if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
521
+				$items['view_related_messages'] = array(
522
+					'class' => $related_for_icon['css_class'],
523
+					'desc'  => $related_for_icon['label'],
524
+				);
525
+			}
526
+		}
527
+		return $items;
528
+	}
529
+
530
+
531
+	/**
532
+	 * This is the callback method for the duplicate event route
533
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
534
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
535
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
536
+	 * After duplication the redirect is to the new event edit page.
537
+	 *
538
+	 * @return void
539
+	 * @throws EE_Error If EE_Event is not available with given ID
540
+	 * @throws InvalidArgumentException
541
+	 * @throws InvalidDataTypeException
542
+	 * @throws InvalidInterfaceException
543
+	 * @throws ReflectionException
544
+	 * @access protected
545
+	 */
546
+	protected function _duplicate_event()
547
+	{
548
+		// first make sure the ID for the event is in the request.
549
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
550
+		if (! isset($this->_req_data['EVT_ID'])) {
551
+			EE_Error::add_error(
552
+				esc_html__(
553
+					'In order to duplicate an event an Event ID is required.  None was given.',
554
+					'event_espresso'
555
+				),
556
+				__FILE__,
557
+				__FUNCTION__,
558
+				__LINE__
559
+			);
560
+			$this->_redirect_after_action(false, '', '', array(), true);
561
+			return;
562
+		}
563
+		// k we've got EVT_ID so let's use that to get the event we'll duplicate
564
+		$orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
565
+		if (! $orig_event instanceof EE_Event) {
566
+			throw new EE_Error(
567
+				sprintf(
568
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
569
+					$this->_req_data['EVT_ID']
570
+				)
571
+			);
572
+		}
573
+		// k now let's clone the $orig_event before getting relations
574
+		$new_event = clone $orig_event;
575
+		// original datetimes
576
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
577
+		// other original relations
578
+		$orig_ven = $orig_event->get_many_related('Venue');
579
+		// reset the ID and modify other details to make it clear this is a dupe
580
+		$new_event->set('EVT_ID', 0);
581
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
582
+		$new_event->set('EVT_name', $new_name);
583
+		$new_event->set(
584
+			'EVT_slug',
585
+			wp_unique_post_slug(
586
+				sanitize_title($orig_event->name()),
587
+				0,
588
+				'publish',
589
+				'espresso_events',
590
+				0
591
+			)
592
+		);
593
+		$new_event->set('status', 'draft');
594
+		// duplicate discussion settings
595
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
596
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
597
+		// save the new event
598
+		$new_event->save();
599
+		// venues
600
+		foreach ($orig_ven as $ven) {
601
+			$new_event->_add_relation_to($ven, 'Venue');
602
+		}
603
+		$new_event->save();
604
+		// now we need to get the question group relations and handle that
605
+		// first primary question groups
606
+		$orig_primary_qgs = $orig_event->get_many_related(
607
+			'Question_Group',
608
+			[['Event_Question_Group.EQG_primary' => true]]
609
+		);
610
+		if (! empty($orig_primary_qgs)) {
611
+			foreach ($orig_primary_qgs as $id => $obj) {
612
+				if ($obj instanceof EE_Question_Group) {
613
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
614
+				}
615
+			}
616
+		}
617
+		// next additional attendee question groups
618
+		$orig_additional_qgs = $orig_event->get_many_related(
619
+			'Question_Group',
620
+			[['Event_Question_Group.EQG_additional' => true]]
621
+		);
622
+		if (! empty($orig_additional_qgs)) {
623
+			foreach ($orig_additional_qgs as $id => $obj) {
624
+				if ($obj instanceof EE_Question_Group) {
625
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
626
+				}
627
+			}
628
+		}
629
+
630
+		$new_event->save();
631
+
632
+		// k now that we have the new event saved we can loop through the datetimes and start adding relations.
633
+		$cloned_tickets = array();
634
+		foreach ($orig_datetimes as $orig_dtt) {
635
+			if (! $orig_dtt instanceof EE_Datetime) {
636
+				continue;
637
+			}
638
+			$new_dtt = clone $orig_dtt;
639
+			$orig_tkts = $orig_dtt->tickets();
640
+			// save new dtt then add to event
641
+			$new_dtt->set('DTT_ID', 0);
642
+			$new_dtt->set('DTT_sold', 0);
643
+			$new_dtt->set_reserved(0);
644
+			$new_dtt->save();
645
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
646
+			$new_event->save();
647
+			// now let's get the ticket relations setup.
648
+			foreach ((array) $orig_tkts as $orig_tkt) {
649
+				// it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
650
+				if (! $orig_tkt instanceof EE_Ticket) {
651
+					continue;
652
+				}
653
+				// is this ticket archived?  If it is then let's skip
654
+				if ($orig_tkt->get('TKT_deleted')) {
655
+					continue;
656
+				}
657
+				// does this original ticket already exist in the clone_tickets cache?
658
+				//  If so we'll just use the new ticket from it.
659
+				if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
660
+					$new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
661
+				} else {
662
+					$new_tkt = clone $orig_tkt;
663
+					// get relations on the $orig_tkt that we need to setup.
664
+					$orig_prices = $orig_tkt->prices();
665
+					$new_tkt->set('TKT_ID', 0);
666
+					$new_tkt->set('TKT_sold', 0);
667
+					$new_tkt->set('TKT_reserved', 0);
668
+					$new_tkt->save(); // make sure new ticket has ID.
669
+					// price relations on new ticket need to be setup.
670
+					foreach ($orig_prices as $orig_price) {
671
+						$new_price = clone $orig_price;
672
+						$new_price->set('PRC_ID', 0);
673
+						$new_price->save();
674
+						$new_tkt->_add_relation_to($new_price, 'Price');
675
+						$new_tkt->save();
676
+					}
677
+
678
+					do_action(
679
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
680
+						$orig_tkt,
681
+						$new_tkt,
682
+						$orig_prices,
683
+						$orig_event,
684
+						$orig_dtt,
685
+						$new_dtt
686
+					);
687
+				}
688
+				// k now we can add the new ticket as a relation to the new datetime
689
+				// and make sure its added to our cached $cloned_tickets array
690
+				// for use with later datetimes that have the same ticket.
691
+				$new_dtt->_add_relation_to($new_tkt, 'Ticket');
692
+				$new_dtt->save();
693
+				$cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
694
+			}
695
+		}
696
+		// clone taxonomy information
697
+		$taxonomies_to_clone_with = apply_filters(
698
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
699
+			array('espresso_event_categories', 'espresso_event_type', 'post_tag')
700
+		);
701
+		// get terms for original event (notice)
702
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
703
+		// loop through terms and add them to new event.
704
+		foreach ($orig_terms as $term) {
705
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
706
+		}
707
+
708
+		// duplicate other core WP_Post items for this event.
709
+		// post thumbnail (feature image).
710
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
711
+		if ($feature_image_id) {
712
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
713
+		}
714
+
715
+		// duplicate page_template setting
716
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
717
+		if ($page_template) {
718
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
719
+		}
720
+
721
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
722
+		// now let's redirect to the edit page for this duplicated event if we have a new event id.
723
+		if ($new_event->ID()) {
724
+			$redirect_args = array(
725
+				'post'   => $new_event->ID(),
726
+				'action' => 'edit',
727
+			);
728
+			EE_Error::add_success(
729
+				esc_html__(
730
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
731
+					'event_espresso'
732
+				)
733
+			);
734
+		} else {
735
+			$redirect_args = array(
736
+				'action' => 'default',
737
+			);
738
+			EE_Error::add_error(
739
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
740
+				__FILE__,
741
+				__FUNCTION__,
742
+				__LINE__
743
+			);
744
+		}
745
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
746
+	}
747
+
748
+
749
+	/**
750
+	 * Generates output for the import page.
751
+	 *
752
+	 * @throws DomainException
753
+	 * @throws EE_Error
754
+	 * @throws InvalidArgumentException
755
+	 * @throws InvalidDataTypeException
756
+	 * @throws InvalidInterfaceException
757
+	 */
758
+	protected function _import_page()
759
+	{
760
+		$title = esc_html__('Import', 'event_espresso');
761
+		$intro = esc_html__(
762
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
763
+			'event_espresso'
764
+		);
765
+		$form_url = EVENTS_ADMIN_URL;
766
+		$action = 'import_events';
767
+		$type = 'csv';
768
+		$this->_template_args['form'] = EE_Import::instance()->upload_form(
769
+			$title,
770
+			$intro,
771
+			$form_url,
772
+			$action,
773
+			$type
774
+		);
775
+		$this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
776
+			array('action' => 'sample_export_file'),
777
+			$this->_admin_base_url
778
+		);
779
+		$content = EEH_Template::display_template(
780
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
781
+			$this->_template_args,
782
+			true
783
+		);
784
+		$this->_template_args['admin_page_content'] = $content;
785
+		$this->display_admin_page_with_sidebar();
786
+	}
787
+
788
+
789
+	/**
790
+	 * _import_events
791
+	 * This handles displaying the screen and running imports for importing events.
792
+	 *
793
+	 * @return void
794
+	 * @throws EE_Error
795
+	 * @throws InvalidArgumentException
796
+	 * @throws InvalidDataTypeException
797
+	 * @throws InvalidInterfaceException
798
+	 */
799
+	protected function _import_events()
800
+	{
801
+		require_once(EE_CLASSES . 'EE_Import.class.php');
802
+		$success = EE_Import::instance()->import();
803
+		$this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
804
+	}
805
+
806
+
807
+	/**
808
+	 * _events_export
809
+	 * Will export all (or just the given event) to a Excel compatible file.
810
+	 *
811
+	 * @access protected
812
+	 * @return void
813
+	 */
814
+	protected function _events_export()
815
+	{
816
+		if (isset($this->_req_data['EVT_ID'])) {
817
+			$event_ids = $this->_req_data['EVT_ID'];
818
+		} elseif (isset($this->_req_data['EVT_IDs'])) {
819
+			$event_ids = $this->_req_data['EVT_IDs'];
820
+		} else {
821
+			$event_ids = null;
822
+		}
823
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
824
+		$new_request_args = array(
825
+			'export' => 'report',
826
+			'action' => 'all_event_data',
827
+			'EVT_ID' => $event_ids,
828
+		);
829
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
830
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
831
+			require_once(EE_CLASSES . 'EE_Export.class.php');
832
+			$EE_Export = EE_Export::instance($this->_req_data);
833
+			if ($EE_Export instanceof EE_Export) {
834
+				$EE_Export->export();
835
+			}
836
+		}
837
+	}
838
+
839
+
840
+	/**
841
+	 * handle category exports()
842
+	 *
843
+	 * @return void
844
+	 */
845
+	protected function _categories_export()
846
+	{
847
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
848
+		$new_request_args = array(
849
+			'export'       => 'report',
850
+			'action'       => 'categories',
851
+			'category_ids' => $this->_req_data['EVT_CAT_ID'],
852
+		);
853
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
854
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
855
+			require_once(EE_CLASSES . 'EE_Export.class.php');
856
+			$EE_Export = EE_Export::instance($this->_req_data);
857
+			if ($EE_Export instanceof EE_Export) {
858
+				$EE_Export->export();
859
+			}
860
+		}
861
+	}
862
+
863
+
864
+	/**
865
+	 * Creates a sample CSV file for importing
866
+	 */
867
+	protected function _sample_export_file()
868
+	{
869
+		$EE_Export = EE_Export::instance();
870
+		if ($EE_Export instanceof EE_Export) {
871
+			$EE_Export->export();
872
+		}
873
+	}
874
+
875
+
876
+	/*************        Template Settings        *************/
877
+	/**
878
+	 * Generates template settings page output
879
+	 *
880
+	 * @throws DomainException
881
+	 * @throws EE_Error
882
+	 * @throws InvalidArgumentException
883
+	 * @throws InvalidDataTypeException
884
+	 * @throws InvalidInterfaceException
885
+	 */
886
+	protected function _template_settings()
887
+	{
888
+		$this->_template_args['values'] = $this->_yes_no_values;
889
+		/**
890
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
891
+		 * from General_Settings_Admin_Page to here.
892
+		 */
893
+		$this->_template_args = apply_filters(
894
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
895
+			$this->_template_args
896
+		);
897
+		$this->_set_add_edit_form_tags('update_template_settings');
898
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
899
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
900
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
901
+			$this->_template_args,
902
+			true
903
+		);
904
+		$this->display_admin_page_with_sidebar();
905
+	}
906
+
907
+
908
+	/**
909
+	 * Handler for updating template settings.
910
+	 *
911
+	 * @throws EE_Error
912
+	 * @throws InvalidArgumentException
913
+	 * @throws InvalidDataTypeException
914
+	 * @throws InvalidInterfaceException
915
+	 */
916
+	protected function _update_template_settings()
917
+	{
918
+		/**
919
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
920
+		 * from General_Settings_Admin_Page to here.
921
+		 */
922
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
923
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
924
+			EE_Registry::instance()->CFG->template_settings,
925
+			$this->_req_data
926
+		);
927
+		// update custom post type slugs and detect if we need to flush rewrite rules
928
+		$old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
929
+		EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
930
+			? EE_Registry::instance()->CFG->core->event_cpt_slug
931
+			: EEH_URL::slugify($this->_req_data['event_cpt_slug'], 'events');
932
+		$what = 'Template Settings';
933
+		$success = $this->_update_espresso_configuration(
934
+			$what,
935
+			EE_Registry::instance()->CFG->template_settings,
936
+			__FILE__,
937
+			__FUNCTION__,
938
+			__LINE__
939
+		);
940
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug !== $old_slug) {
941
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
942
+			$rewrite_rules = LoaderFactory::getLoader()->getShared(
943
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
944
+			);
945
+			$rewrite_rules->flush();
946
+		}
947
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
948
+	}
949
+
950
+
951
+	/**
952
+	 * _premium_event_editor_meta_boxes
953
+	 * add all metaboxes related to the event_editor
954
+	 *
955
+	 * @access protected
956
+	 * @return void
957
+	 * @throws EE_Error
958
+	 * @throws InvalidArgumentException
959
+	 * @throws InvalidDataTypeException
960
+	 * @throws InvalidInterfaceException
961
+	 * @throws ReflectionException
962
+	 */
963
+	protected function _premium_event_editor_meta_boxes()
964
+	{
965
+		$this->verify_cpt_object();
966
+		add_meta_box(
967
+			'espresso_event_editor_event_options',
968
+			esc_html__('Event Registration Options', 'event_espresso'),
969
+			array($this, 'registration_options_meta_box'),
970
+			$this->page_slug,
971
+			'side',
972
+			'core'
973
+		);
974
+	}
975
+
976
+
977
+	/**
978
+	 * override caf metabox
979
+	 *
980
+	 * @return void
981
+	 * @throws DomainException
982
+	 * @throws EE_Error
983
+	 */
984
+	public function registration_options_meta_box()
985
+	{
986
+		$yes_no_values = array(
987
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
988
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
989
+		);
990
+		$default_reg_status_values = EEM_Registration::reg_status_array(
991
+			array(
992
+				EEM_Registration::status_id_cancelled,
993
+				EEM_Registration::status_id_declined,
994
+				EEM_Registration::status_id_incomplete,
995
+				EEM_Registration::status_id_wait_list,
996
+			),
997
+			true
998
+		);
999
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1000
+		$template_args['_event'] = $this->_cpt_model_obj;
1001
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1002
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1003
+			'default_reg_status',
1004
+			$default_reg_status_values,
1005
+			$this->_cpt_model_obj->default_registration_status()
1006
+		);
1007
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1008
+			'display_desc',
1009
+			$yes_no_values,
1010
+			$this->_cpt_model_obj->display_description()
1011
+		);
1012
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1013
+			'display_ticket_selector',
1014
+			$yes_no_values,
1015
+			$this->_cpt_model_obj->display_ticket_selector(),
1016
+			'',
1017
+			'',
1018
+			false
1019
+		);
1020
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
1021
+			'EVT_default_registration_status',
1022
+			$default_reg_status_values,
1023
+			$this->_cpt_model_obj->default_registration_status()
1024
+		);
1025
+		$template_args['additional_registration_options'] = apply_filters(
1026
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1027
+			'',
1028
+			$template_args,
1029
+			$yes_no_values,
1030
+			$default_reg_status_values
1031
+		);
1032
+		EEH_Template::display_template(
1033
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
1034
+			$template_args
1035
+		);
1036
+	}
1037
+
1038
+
1039
+
1040
+	/**
1041
+	 * wp_list_table_mods for caf
1042
+	 * ============================
1043
+	 */
1044
+	/**
1045
+	 * hook into list table filters and provide filters for caffeinated list table
1046
+	 *
1047
+	 * @param array $old_filters    any existing filters present
1048
+	 * @param array $list_table_obj the list table object
1049
+	 * @return array                  new filters
1050
+	 * @throws EE_Error
1051
+	 * @throws InvalidArgumentException
1052
+	 * @throws InvalidDataTypeException
1053
+	 * @throws InvalidInterfaceException
1054
+	 * @throws ReflectionException
1055
+	 */
1056
+	public function list_table_filters($old_filters, $list_table_obj)
1057
+	{
1058
+		$filters = array();
1059
+		// first month/year filters
1060
+		$filters[] = $this->espresso_event_months_dropdown();
1061
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1062
+		// active status dropdown
1063
+		if ($status !== 'draft') {
1064
+			$filters[] = $this->active_status_dropdown(
1065
+				isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
1066
+			);
1067
+			$filters[] = $this->venuesDropdown(
1068
+				isset($this->_req_data['venue']) ? $this->_req_data['venue'] : ''
1069
+			);
1070
+		}
1071
+		// category filter
1072
+		$filters[] = $this->category_dropdown();
1073
+		return array_merge($old_filters, $filters);
1074
+	}
1075
+
1076
+
1077
+	/**
1078
+	 * espresso_event_months_dropdown
1079
+	 *
1080
+	 * @access public
1081
+	 * @return string                dropdown listing month/year selections for events.
1082
+	 */
1083
+	public function espresso_event_months_dropdown()
1084
+	{
1085
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
1086
+		// Note we need to include any other filters that are set!
1087
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1088
+		// categories?
1089
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1090
+			? $this->_req_data['EVT_CAT']
1091
+			: null;
1092
+		// active status?
1093
+		$active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
1094
+		$cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1095
+		return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1096
+	}
1097
+
1098
+
1099
+	/**
1100
+	 * returns a list of "active" statuses on the event
1101
+	 *
1102
+	 * @param  string $current_value whatever the current active status is
1103
+	 * @return string
1104
+	 */
1105
+	public function active_status_dropdown($current_value = '')
1106
+	{
1107
+		$select_name = 'active_status';
1108
+		$values = array(
1109
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1110
+			'active'   => esc_html__('Active', 'event_espresso'),
1111
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1112
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1113
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1114
+		);
1115
+
1116
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1117
+	}
1118
+
1119
+
1120
+	/**
1121
+	 * returns a list of "venues"
1122
+	 *
1123
+	 * @param string $current_value whatever the current active status is
1124
+	 * @return string
1125
+	 * @throws EE_Error
1126
+	 * @throws InvalidArgumentException
1127
+	 * @throws InvalidDataTypeException
1128
+	 * @throws InvalidInterfaceException
1129
+	 * @throws ReflectionException
1130
+	 */
1131
+	protected function venuesDropdown($current_value = '')
1132
+	{
1133
+		$select_name = 'venue';
1134
+		$values = array(
1135
+			'' => esc_html__('All Venues', 'event_espresso'),
1136
+		);
1137
+		// populate the list of venues.
1138
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1139
+		$venues = $venue_model->get_all(array('order_by' => array('VNU_name' => 'ASC')));
1140
+
1141
+		foreach ($venues as $venue) {
1142
+			$values[ $venue->ID() ] = $venue->name();
1143
+		}
1144
+
1145
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1146
+	}
1147
+
1148
+
1149
+	/**
1150
+	 * output a dropdown of the categories for the category filter on the event admin list table
1151
+	 *
1152
+	 * @access  public
1153
+	 * @return string html
1154
+	 */
1155
+	public function category_dropdown()
1156
+	{
1157
+		$cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1158
+		return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1159
+	}
1160
+
1161
+
1162
+	/**
1163
+	 * get total number of events today
1164
+	 *
1165
+	 * @access public
1166
+	 * @return int
1167
+	 * @throws EE_Error
1168
+	 * @throws InvalidArgumentException
1169
+	 * @throws InvalidDataTypeException
1170
+	 * @throws InvalidInterfaceException
1171
+	 */
1172
+	public function total_events_today()
1173
+	{
1174
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1175
+			'DTT_EVT_start',
1176
+			date('Y-m-d') . ' 00:00:00',
1177
+			'Y-m-d H:i:s',
1178
+			'UTC'
1179
+		);
1180
+		$end = EEM_Datetime::instance()->convert_datetime_for_query(
1181
+			'DTT_EVT_start',
1182
+			date('Y-m-d') . ' 23:59:59',
1183
+			'Y-m-d H:i:s',
1184
+			'UTC'
1185
+		);
1186
+		$where = array(
1187
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1188
+		);
1189
+		return EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1190
+	}
1191
+
1192
+
1193
+	/**
1194
+	 * get total number of events this month
1195
+	 *
1196
+	 * @access public
1197
+	 * @return int
1198
+	 * @throws EE_Error
1199
+	 * @throws InvalidArgumentException
1200
+	 * @throws InvalidDataTypeException
1201
+	 * @throws InvalidInterfaceException
1202
+	 */
1203
+	public function total_events_this_month()
1204
+	{
1205
+		// Dates
1206
+		$this_year_r = date('Y');
1207
+		$this_month_r = date('m');
1208
+		$days_this_month = date('t');
1209
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1210
+			'DTT_EVT_start',
1211
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1212
+			'Y-m-d H:i:s',
1213
+			'UTC'
1214
+		);
1215
+		$end = EEM_Datetime::instance()->convert_datetime_for_query(
1216
+			'DTT_EVT_start',
1217
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1218
+			'Y-m-d H:i:s',
1219
+			'UTC'
1220
+		);
1221
+		$where = array(
1222
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1223
+		);
1224
+		return EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1225
+	}
1226
+
1227
+
1228
+	/** DEFAULT TICKETS STUFF **/
1229
+
1230
+	/**
1231
+	 * Output default tickets list table view.
1232
+	 *
1233
+	 * @throws DomainException
1234
+	 * @throws EE_Error
1235
+	 * @throws InvalidArgumentException
1236
+	 * @throws InvalidDataTypeException
1237
+	 * @throws InvalidInterfaceException
1238
+	 */
1239
+	public function _tickets_overview_list_table()
1240
+	{
1241
+		$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1242
+		$this->display_admin_list_table_page_with_no_sidebar();
1243
+	}
1244
+
1245
+
1246
+	/**
1247
+	 * @param int  $per_page
1248
+	 * @param bool $count
1249
+	 * @param bool $trashed
1250
+	 * @return EE_Soft_Delete_Base_Class[]|int
1251
+	 * @throws EE_Error
1252
+	 * @throws InvalidArgumentException
1253
+	 * @throws InvalidDataTypeException
1254
+	 * @throws InvalidInterfaceException
1255
+	 */
1256
+	public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1257
+	{
1258
+		$orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1259
+		$order = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1260
+		switch ($orderby) {
1261
+			case 'TKT_name':
1262
+				$orderby = array('TKT_name' => $order);
1263
+				break;
1264
+			case 'TKT_price':
1265
+				$orderby = array('TKT_price' => $order);
1266
+				break;
1267
+			case 'TKT_uses':
1268
+				$orderby = array('TKT_uses' => $order);
1269
+				break;
1270
+			case 'TKT_min':
1271
+				$orderby = array('TKT_min' => $order);
1272
+				break;
1273
+			case 'TKT_max':
1274
+				$orderby = array('TKT_max' => $order);
1275
+				break;
1276
+			case 'TKT_qty':
1277
+				$orderby = array('TKT_qty' => $order);
1278
+				break;
1279
+		}
1280
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1281
+			? $this->_req_data['paged']
1282
+			: 1;
1283
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1284
+			? $this->_req_data['perpage']
1285
+			: $per_page;
1286
+		$_where = array(
1287
+			'TKT_is_default' => 1,
1288
+			'TKT_deleted'    => $trashed,
1289
+		);
1290
+		$offset = ($current_page - 1) * $per_page;
1291
+		$limit = array($offset, $per_page);
1292
+		if (isset($this->_req_data['s'])) {
1293
+			$sstr = '%' . $this->_req_data['s'] . '%';
1294
+			$_where['OR'] = array(
1295
+				'TKT_name'        => array('LIKE', $sstr),
1296
+				'TKT_description' => array('LIKE', $sstr),
1297
+			);
1298
+		}
1299
+		$query_params = array(
1300
+			$_where,
1301
+			'order_by' => $orderby,
1302
+			'limit'    => $limit,
1303
+			'group_by' => 'TKT_ID',
1304
+		);
1305
+		if ($count) {
1306
+			return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1307
+		}
1308
+		return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1309
+	}
1310
+
1311
+
1312
+	/**
1313
+	 * @param bool $trash
1314
+	 * @throws EE_Error
1315
+	 * @throws InvalidArgumentException
1316
+	 * @throws InvalidDataTypeException
1317
+	 * @throws InvalidInterfaceException
1318
+	 */
1319
+	protected function _trash_or_restore_ticket($trash = false)
1320
+	{
1321
+		$success = 1;
1322
+		$TKT = EEM_Ticket::instance();
1323
+		// checkboxes?
1324
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1325
+			// if array has more than one element then success message should be plural
1326
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1327
+			// cycle thru the boxes
1328
+			foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1329
+				if ($trash) {
1330
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1331
+						$success = 0;
1332
+					}
1333
+				} elseif (! $TKT->restore_by_ID($TKT_ID)) {
1334
+					$success = 0;
1335
+				}
1336
+			}
1337
+		} else {
1338
+			// grab single id and trash
1339
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1340
+			if ($trash) {
1341
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1342
+					$success = 0;
1343
+				}
1344
+			} elseif (! $TKT->restore_by_ID($TKT_ID)) {
1345
+				$success = 0;
1346
+			}
1347
+		}
1348
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1349
+		$query_args = array(
1350
+			'action' => 'ticket_list_table',
1351
+			'status' => $trash ? '' : 'trashed',
1352
+		);
1353
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1354
+	}
1355
+
1356
+
1357
+	/**
1358
+	 * Handles trashing default ticket.
1359
+	 *
1360
+	 * @throws EE_Error
1361
+	 * @throws InvalidArgumentException
1362
+	 * @throws InvalidDataTypeException
1363
+	 * @throws InvalidInterfaceException
1364
+	 * @throws ReflectionException
1365
+	 */
1366
+	protected function _delete_ticket()
1367
+	{
1368
+		$success = 1;
1369
+		// checkboxes?
1370
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1371
+			// if array has more than one element then success message should be plural
1372
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1373
+			// cycle thru the boxes
1374
+			foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1375
+				// delete
1376
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1377
+					$success = 0;
1378
+				}
1379
+			}
1380
+		} else {
1381
+			// grab single id and trash
1382
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1383
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1384
+				$success = 0;
1385
+			}
1386
+		}
1387
+		$action_desc = 'deleted';
1388
+		// fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1389
+		$ticket_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
1390
+			[['TKT_is_default' => 1]],
1391
+			'TKT_ID',
1392
+			true
1393
+		);
1394
+		$query_args = $ticket_count
1395
+			? []
1396
+			: [
1397
+				'action' => 'ticket_list_table',
1398
+				'status' => 'trashed'
1399
+			];
1400
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1401
+	}
1402
+
1403
+
1404
+	/**
1405
+	 * @param int $TKT_ID
1406
+	 * @return bool|int
1407
+	 * @throws EE_Error
1408
+	 * @throws InvalidArgumentException
1409
+	 * @throws InvalidDataTypeException
1410
+	 * @throws InvalidInterfaceException
1411
+	 * @throws ReflectionException
1412
+	 */
1413
+	protected function _delete_the_ticket($TKT_ID)
1414
+	{
1415
+		$ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1416
+		if (! $ticket instanceof EE_Ticket) {
1417
+			return false;
1418
+		}
1419
+		$ticket->_remove_relations('Datetime');
1420
+		// delete all related prices first
1421
+		$ticket->delete_related_permanently('Price');
1422
+		return $ticket->delete_permanently();
1423
+	}
1424 1424
 }
Please login to merge, or discard this patch.
Spacing   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -35,10 +35,10 @@  discard block
 block discarded – undo
35 35
      */
36 36
     public function __construct($routing = true)
37 37
     {
38
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
39
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
40
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
41
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
38
+        if ( ! defined('EVENTS_CAF_TEMPLATE_PATH')) {
39
+            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND.'events/templates/');
40
+            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND.'events/assets/');
41
+            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL.'events/assets/');
42 42
         }
43 43
         parent::__construct($routing);
44 44
         $this->admin_config = $this->loader->getShared('EE_Admin_Config');
@@ -56,7 +56,7 @@  discard block
 block discarded – undo
56 56
      */
57 57
     protected function _extend_page_config()
58 58
     {
59
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
59
+        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND.'events';
60 60
         // is there a evt_id in the request?
61 61
         $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
62 62
             ? $this->_req_data['EVT_ID']
@@ -107,8 +107,8 @@  discard block
 block discarded – undo
107 107
                 'capability' => 'manage_options',
108 108
                 'noheader'   => true,
109 109
             ),
110
-        );        // don't load these meta boxes if using the advanced editor
111
-        if (! $this->admin_config->useAdvancedEditor()) {
110
+        ); // don't load these meta boxes if using the advanced editor
111
+        if ( ! $this->admin_config->useAdvancedEditor()) {
112 112
             $this->_page_config['create_new']['metaboxes'][] = '_premium_event_editor_meta_boxes';
113 113
             $this->_page_config['edit']['metaboxes'][] = '_premium_event_editor_meta_boxes';
114 114
             $this->_page_config['create_new']['qtips'][] = 'EE_Event_Editor_Tips';
@@ -302,7 +302,7 @@  discard block
 block discarded – undo
302 302
     {
303 303
         $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
304 304
         // make sure this is only when editing
305
-        if (! empty($id)) {
305
+        if ( ! empty($id)) {
306 306
             $href = EE_Admin_Page::add_query_args_and_nonce(
307 307
                 array('action' => 'duplicate_event', 'EVT_ID' => $id),
308 308
                 $this->_admin_base_url
@@ -352,10 +352,10 @@  discard block
 block discarded – undo
352 352
      */
353 353
     public function load_scripts_styles_edit()
354 354
     {
355
-        if (! $this->admin_config->useAdvancedEditor()) {
355
+        if ( ! $this->admin_config->useAdvancedEditor()) {
356 356
             wp_register_script(
357 357
                 'ee-event-editor-heartbeat',
358
-                EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
358
+                EVENTS_CAF_ASSETS_URL.'event-editor-heartbeat.js',
359 359
                 ['ee_admin_js', 'heartbeat'],
360 360
                 EVENT_ESPRESSO_VERSION,
361 361
                 true
@@ -380,7 +380,7 @@  discard block
 block discarded – undo
380 380
     public function add_additional_datetime_button($template, $template_args)
381 381
     {
382 382
         return EEH_Template::display_template(
383
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
383
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_add_additional_time.template.php',
384 384
             $template_args,
385 385
             true
386 386
         );
@@ -398,7 +398,7 @@  discard block
 block discarded – undo
398 398
     public function add_datetime_clone_button($template, $template_args)
399 399
     {
400 400
         return EEH_Template::display_template(
401
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
401
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_metabox_clone_button.template.php',
402 402
             $template_args,
403 403
             true
404 404
         );
@@ -416,7 +416,7 @@  discard block
 block discarded – undo
416 416
     public function datetime_timezones_template($template, $template_args)
417 417
     {
418 418
         return EEH_Template::display_template(
419
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
419
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_timezones.template.php',
420 420
             $template_args,
421 421
             true
422 422
         );
@@ -547,7 +547,7 @@  discard block
 block discarded – undo
547 547
     {
548 548
         // first make sure the ID for the event is in the request.
549 549
         //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
550
-        if (! isset($this->_req_data['EVT_ID'])) {
550
+        if ( ! isset($this->_req_data['EVT_ID'])) {
551 551
             EE_Error::add_error(
552 552
                 esc_html__(
553 553
                     'In order to duplicate an event an Event ID is required.  None was given.',
@@ -562,7 +562,7 @@  discard block
 block discarded – undo
562 562
         }
563 563
         // k we've got EVT_ID so let's use that to get the event we'll duplicate
564 564
         $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
565
-        if (! $orig_event instanceof EE_Event) {
565
+        if ( ! $orig_event instanceof EE_Event) {
566 566
             throw new EE_Error(
567 567
                 sprintf(
568 568
                     esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
@@ -578,7 +578,7 @@  discard block
 block discarded – undo
578 578
         $orig_ven = $orig_event->get_many_related('Venue');
579 579
         // reset the ID and modify other details to make it clear this is a dupe
580 580
         $new_event->set('EVT_ID', 0);
581
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
581
+        $new_name = $new_event->name().' '.esc_html__('**DUPLICATE**', 'event_espresso');
582 582
         $new_event->set('EVT_name', $new_name);
583 583
         $new_event->set(
584 584
             'EVT_slug',
@@ -607,7 +607,7 @@  discard block
 block discarded – undo
607 607
             'Question_Group',
608 608
             [['Event_Question_Group.EQG_primary' => true]]
609 609
         );
610
-        if (! empty($orig_primary_qgs)) {
610
+        if ( ! empty($orig_primary_qgs)) {
611 611
             foreach ($orig_primary_qgs as $id => $obj) {
612 612
                 if ($obj instanceof EE_Question_Group) {
613 613
                     $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
@@ -619,7 +619,7 @@  discard block
 block discarded – undo
619 619
             'Question_Group',
620 620
             [['Event_Question_Group.EQG_additional' => true]]
621 621
         );
622
-        if (! empty($orig_additional_qgs)) {
622
+        if ( ! empty($orig_additional_qgs)) {
623 623
             foreach ($orig_additional_qgs as $id => $obj) {
624 624
                 if ($obj instanceof EE_Question_Group) {
625 625
                     $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
@@ -632,7 +632,7 @@  discard block
 block discarded – undo
632 632
         // k now that we have the new event saved we can loop through the datetimes and start adding relations.
633 633
         $cloned_tickets = array();
634 634
         foreach ($orig_datetimes as $orig_dtt) {
635
-            if (! $orig_dtt instanceof EE_Datetime) {
635
+            if ( ! $orig_dtt instanceof EE_Datetime) {
636 636
                 continue;
637 637
             }
638 638
             $new_dtt = clone $orig_dtt;
@@ -647,7 +647,7 @@  discard block
 block discarded – undo
647 647
             // now let's get the ticket relations setup.
648 648
             foreach ((array) $orig_tkts as $orig_tkt) {
649 649
                 // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
650
-                if (! $orig_tkt instanceof EE_Ticket) {
650
+                if ( ! $orig_tkt instanceof EE_Ticket) {
651 651
                     continue;
652 652
                 }
653 653
                 // is this ticket archived?  If it is then let's skip
@@ -656,8 +656,8 @@  discard block
 block discarded – undo
656 656
                 }
657 657
                 // does this original ticket already exist in the clone_tickets cache?
658 658
                 //  If so we'll just use the new ticket from it.
659
-                if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
660
-                    $new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
659
+                if (isset($cloned_tickets[$orig_tkt->ID()])) {
660
+                    $new_tkt = $cloned_tickets[$orig_tkt->ID()];
661 661
                 } else {
662 662
                     $new_tkt = clone $orig_tkt;
663 663
                     // get relations on the $orig_tkt that we need to setup.
@@ -690,7 +690,7 @@  discard block
 block discarded – undo
690 690
                 // for use with later datetimes that have the same ticket.
691 691
                 $new_dtt->_add_relation_to($new_tkt, 'Ticket');
692 692
                 $new_dtt->save();
693
-                $cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
693
+                $cloned_tickets[$orig_tkt->ID()] = $new_tkt;
694 694
             }
695 695
         }
696 696
         // clone taxonomy information
@@ -777,7 +777,7 @@  discard block
 block discarded – undo
777 777
             $this->_admin_base_url
778 778
         );
779 779
         $content = EEH_Template::display_template(
780
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
780
+            EVENTS_CAF_TEMPLATE_PATH.'import_page.template.php',
781 781
             $this->_template_args,
782 782
             true
783 783
         );
@@ -798,7 +798,7 @@  discard block
 block discarded – undo
798 798
      */
799 799
     protected function _import_events()
800 800
     {
801
-        require_once(EE_CLASSES . 'EE_Import.class.php');
801
+        require_once(EE_CLASSES.'EE_Import.class.php');
802 802
         $success = EE_Import::instance()->import();
803 803
         $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
804 804
     }
@@ -827,8 +827,8 @@  discard block
 block discarded – undo
827 827
             'EVT_ID' => $event_ids,
828 828
         );
829 829
         $this->_req_data = array_merge($this->_req_data, $new_request_args);
830
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
831
-            require_once(EE_CLASSES . 'EE_Export.class.php');
830
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
831
+            require_once(EE_CLASSES.'EE_Export.class.php');
832 832
             $EE_Export = EE_Export::instance($this->_req_data);
833 833
             if ($EE_Export instanceof EE_Export) {
834 834
                 $EE_Export->export();
@@ -851,8 +851,8 @@  discard block
 block discarded – undo
851 851
             'category_ids' => $this->_req_data['EVT_CAT_ID'],
852 852
         );
853 853
         $this->_req_data = array_merge($this->_req_data, $new_request_args);
854
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
855
-            require_once(EE_CLASSES . 'EE_Export.class.php');
854
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
855
+            require_once(EE_CLASSES.'EE_Export.class.php');
856 856
             $EE_Export = EE_Export::instance($this->_req_data);
857 857
             if ($EE_Export instanceof EE_Export) {
858 858
                 $EE_Export->export();
@@ -897,7 +897,7 @@  discard block
 block discarded – undo
897 897
         $this->_set_add_edit_form_tags('update_template_settings');
898 898
         $this->_set_publish_post_box_vars(null, false, false, null, false);
899 899
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
900
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
900
+            EVENTS_CAF_TEMPLATE_PATH.'template_settings.template.php',
901 901
             $this->_template_args,
902 902
             true
903 903
         );
@@ -1030,7 +1030,7 @@  discard block
 block discarded – undo
1030 1030
             $default_reg_status_values
1031 1031
         );
1032 1032
         EEH_Template::display_template(
1033
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
1033
+            EVENTS_CAF_TEMPLATE_PATH.'event_registration_options.template.php',
1034 1034
             $template_args
1035 1035
         );
1036 1036
     }
@@ -1139,7 +1139,7 @@  discard block
 block discarded – undo
1139 1139
         $venues = $venue_model->get_all(array('order_by' => array('VNU_name' => 'ASC')));
1140 1140
 
1141 1141
         foreach ($venues as $venue) {
1142
-            $values[ $venue->ID() ] = $venue->name();
1142
+            $values[$venue->ID()] = $venue->name();
1143 1143
         }
1144 1144
 
1145 1145
         return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
@@ -1173,13 +1173,13 @@  discard block
 block discarded – undo
1173 1173
     {
1174 1174
         $start = EEM_Datetime::instance()->convert_datetime_for_query(
1175 1175
             'DTT_EVT_start',
1176
-            date('Y-m-d') . ' 00:00:00',
1176
+            date('Y-m-d').' 00:00:00',
1177 1177
             'Y-m-d H:i:s',
1178 1178
             'UTC'
1179 1179
         );
1180 1180
         $end = EEM_Datetime::instance()->convert_datetime_for_query(
1181 1181
             'DTT_EVT_start',
1182
-            date('Y-m-d') . ' 23:59:59',
1182
+            date('Y-m-d').' 23:59:59',
1183 1183
             'Y-m-d H:i:s',
1184 1184
             'UTC'
1185 1185
         );
@@ -1208,13 +1208,13 @@  discard block
 block discarded – undo
1208 1208
         $days_this_month = date('t');
1209 1209
         $start = EEM_Datetime::instance()->convert_datetime_for_query(
1210 1210
             'DTT_EVT_start',
1211
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1211
+            $this_year_r.'-'.$this_month_r.'-01 00:00:00',
1212 1212
             'Y-m-d H:i:s',
1213 1213
             'UTC'
1214 1214
         );
1215 1215
         $end = EEM_Datetime::instance()->convert_datetime_for_query(
1216 1216
             'DTT_EVT_start',
1217
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1217
+            $this_year_r.'-'.$this_month_r.'-'.$days_this_month.' 23:59:59',
1218 1218
             'Y-m-d H:i:s',
1219 1219
             'UTC'
1220 1220
         );
@@ -1290,7 +1290,7 @@  discard block
 block discarded – undo
1290 1290
         $offset = ($current_page - 1) * $per_page;
1291 1291
         $limit = array($offset, $per_page);
1292 1292
         if (isset($this->_req_data['s'])) {
1293
-            $sstr = '%' . $this->_req_data['s'] . '%';
1293
+            $sstr = '%'.$this->_req_data['s'].'%';
1294 1294
             $_where['OR'] = array(
1295 1295
                 'TKT_name'        => array('LIKE', $sstr),
1296 1296
                 'TKT_description' => array('LIKE', $sstr),
@@ -1321,16 +1321,16 @@  discard block
 block discarded – undo
1321 1321
         $success = 1;
1322 1322
         $TKT = EEM_Ticket::instance();
1323 1323
         // checkboxes?
1324
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1324
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1325 1325
             // if array has more than one element then success message should be plural
1326 1326
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1327 1327
             // cycle thru the boxes
1328 1328
             foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1329 1329
                 if ($trash) {
1330
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1330
+                    if ( ! $TKT->delete_by_ID($TKT_ID)) {
1331 1331
                         $success = 0;
1332 1332
                     }
1333
-                } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1333
+                } elseif ( ! $TKT->restore_by_ID($TKT_ID)) {
1334 1334
                     $success = 0;
1335 1335
                 }
1336 1336
             }
@@ -1338,10 +1338,10 @@  discard block
 block discarded – undo
1338 1338
             // grab single id and trash
1339 1339
             $TKT_ID = absint($this->_req_data['TKT_ID']);
1340 1340
             if ($trash) {
1341
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1341
+                if ( ! $TKT->delete_by_ID($TKT_ID)) {
1342 1342
                     $success = 0;
1343 1343
                 }
1344
-            } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1344
+            } elseif ( ! $TKT->restore_by_ID($TKT_ID)) {
1345 1345
                 $success = 0;
1346 1346
             }
1347 1347
         }
@@ -1367,20 +1367,20 @@  discard block
 block discarded – undo
1367 1367
     {
1368 1368
         $success = 1;
1369 1369
         // checkboxes?
1370
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1370
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1371 1371
             // if array has more than one element then success message should be plural
1372 1372
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1373 1373
             // cycle thru the boxes
1374 1374
             foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1375 1375
                 // delete
1376
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1376
+                if ( ! $this->_delete_the_ticket($TKT_ID)) {
1377 1377
                     $success = 0;
1378 1378
                 }
1379 1379
             }
1380 1380
         } else {
1381 1381
             // grab single id and trash
1382 1382
             $TKT_ID = absint($this->_req_data['TKT_ID']);
1383
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1383
+            if ( ! $this->_delete_the_ticket($TKT_ID)) {
1384 1384
                 $success = 0;
1385 1385
             }
1386 1386
         }
@@ -1413,7 +1413,7 @@  discard block
 block discarded – undo
1413 1413
     protected function _delete_the_ticket($TKT_ID)
1414 1414
     {
1415 1415
         $ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1416
-        if (! $ticket instanceof EE_Ticket) {
1416
+        if ( ! $ticket instanceof EE_Ticket) {
1417 1417
             return false;
1418 1418
         }
1419 1419
         $ticket->_remove_relations('Datetime');
Please login to merge, or discard this patch.
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2865 added lines, -2865 removed lines patch added patch discarded remove patch
@@ -15,2869 +15,2869 @@
 block discarded – undo
15 15
 class Events_Admin_Page extends EE_Admin_Page_CPT
16 16
 {
17 17
 
18
-    /**
19
-     * This will hold the event object for event_details screen.
20
-     *
21
-     * @access protected
22
-     * @var EE_Event $_event
23
-     */
24
-    protected $_event;
25
-
26
-
27
-    /**
28
-     * This will hold the category object for category_details screen.
29
-     *
30
-     * @var stdClass $_category
31
-     */
32
-    protected $_category;
33
-
34
-
35
-    /**
36
-     * This will hold the event model instance
37
-     *
38
-     * @var EEM_Event $_event_model
39
-     */
40
-    protected $_event_model;
41
-
42
-
43
-    /**
44
-     * @var EE_Event
45
-     */
46
-    protected $_cpt_model_obj = false;
47
-
48
-
49
-    /**
50
-     * Initialize page props for this admin page group.
51
-     */
52
-    protected function _init_page_props()
53
-    {
54
-        $this->page_slug = EVENTS_PG_SLUG;
55
-        $this->page_label = EVENTS_LABEL;
56
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
57
-        $this->_admin_base_path = EVENTS_ADMIN;
58
-        $this->_cpt_model_names = array(
59
-            'create_new' => 'EEM_Event',
60
-            'edit'       => 'EEM_Event',
61
-        );
62
-        $this->_cpt_edit_routes = array(
63
-            'espresso_events' => 'edit',
64
-        );
65
-        add_action(
66
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
67
-            array($this, 'verify_event_edit'),
68
-            10,
69
-            2
70
-        );
71
-    }
72
-
73
-
74
-    /**
75
-     * Sets the ajax hooks used for this admin page group.
76
-     */
77
-    protected function _ajax_hooks()
78
-    {
79
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
80
-    }
81
-
82
-
83
-    /**
84
-     * Sets the page properties for this admin page group.
85
-     */
86
-    protected function _define_page_props()
87
-    {
88
-        $this->_admin_page_title = EVENTS_LABEL;
89
-        $this->_labels = array(
90
-            'buttons'      => array(
91
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
92
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
93
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
94
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
95
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
96
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
97
-            ),
98
-            'editor_title' => array(
99
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
100
-            ),
101
-            'publishbox'   => array(
102
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
103
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
104
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
105
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
106
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
107
-            ),
108
-        );
109
-    }
110
-
111
-
112
-    /**
113
-     * Sets the page routes property for this admin page group.
114
-     */
115
-    protected function _set_page_routes()
116
-    {
117
-        // load formatter helper
118
-        // load field generator helper
119
-        // is there a evt_id in the request?
120
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
121
-            ? $this->_req_data['EVT_ID']
122
-            : 0;
123
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
124
-        $this->_page_routes = array(
125
-            'default'                       => array(
126
-                'func'       => '_events_overview_list_table',
127
-                'capability' => 'ee_read_events',
128
-            ),
129
-            'create_new'                    => array(
130
-                'func'       => '_create_new_cpt_item',
131
-                'capability' => 'ee_edit_events',
132
-            ),
133
-            'edit'                          => array(
134
-                'func'       => '_edit_cpt_item',
135
-                'capability' => 'ee_edit_event',
136
-                'obj_id'     => $evt_id,
137
-            ),
138
-            'copy_event'                    => array(
139
-                'func'       => '_copy_events',
140
-                'capability' => 'ee_edit_event',
141
-                'obj_id'     => $evt_id,
142
-                'noheader'   => true,
143
-            ),
144
-            'trash_event'                   => array(
145
-                'func'       => '_trash_or_restore_event',
146
-                'args'       => array('event_status' => 'trash'),
147
-                'capability' => 'ee_delete_event',
148
-                'obj_id'     => $evt_id,
149
-                'noheader'   => true,
150
-            ),
151
-            'trash_events'                  => array(
152
-                'func'       => '_trash_or_restore_events',
153
-                'args'       => array('event_status' => 'trash'),
154
-                'capability' => 'ee_delete_events',
155
-                'noheader'   => true,
156
-            ),
157
-            'restore_event'                 => array(
158
-                'func'       => '_trash_or_restore_event',
159
-                'args'       => array('event_status' => 'draft'),
160
-                'capability' => 'ee_delete_event',
161
-                'obj_id'     => $evt_id,
162
-                'noheader'   => true,
163
-            ),
164
-            'restore_events'                => array(
165
-                'func'       => '_trash_or_restore_events',
166
-                'args'       => array('event_status' => 'draft'),
167
-                'capability' => 'ee_delete_events',
168
-                'noheader'   => true,
169
-            ),
170
-            'delete_event'                  => array(
171
-                'func'       => '_delete_event',
172
-                'capability' => 'ee_delete_event',
173
-                'obj_id'     => $evt_id,
174
-                'noheader'   => true,
175
-            ),
176
-            'delete_events'                 => array(
177
-                'func'       => '_delete_events',
178
-                'capability' => 'ee_delete_events',
179
-                'noheader'   => true,
180
-            ),
181
-            'view_report'                   => array(
182
-                'func'      => '_view_report',
183
-                'capability' => 'ee_edit_events',
184
-            ),
185
-            'default_event_settings'        => array(
186
-                'func'       => '_default_event_settings',
187
-                'capability' => 'manage_options',
188
-            ),
189
-            'update_default_event_settings' => array(
190
-                'func'       => '_update_default_event_settings',
191
-                'capability' => 'manage_options',
192
-                'noheader'   => true,
193
-            ),
194
-            'template_settings'             => array(
195
-                'func'       => '_template_settings',
196
-                'capability' => 'manage_options',
197
-            ),
198
-            // event category tab related
199
-            'add_category'                  => array(
200
-                'func'       => '_category_details',
201
-                'capability' => 'ee_edit_event_category',
202
-                'args'       => array('add'),
203
-            ),
204
-            'edit_category'                 => array(
205
-                'func'       => '_category_details',
206
-                'capability' => 'ee_edit_event_category',
207
-                'args'       => array('edit'),
208
-            ),
209
-            'delete_categories'             => array(
210
-                'func'       => '_delete_categories',
211
-                'capability' => 'ee_delete_event_category',
212
-                'noheader'   => true,
213
-            ),
214
-            'delete_category'               => array(
215
-                'func'       => '_delete_categories',
216
-                'capability' => 'ee_delete_event_category',
217
-                'noheader'   => true,
218
-            ),
219
-            'insert_category'               => array(
220
-                'func'       => '_insert_or_update_category',
221
-                'args'       => array('new_category' => true),
222
-                'capability' => 'ee_edit_event_category',
223
-                'noheader'   => true,
224
-            ),
225
-            'update_category'               => array(
226
-                'func'       => '_insert_or_update_category',
227
-                'args'       => array('new_category' => false),
228
-                'capability' => 'ee_edit_event_category',
229
-                'noheader'   => true,
230
-            ),
231
-            'category_list'                 => array(
232
-                'func'       => '_category_list_table',
233
-                'capability' => 'ee_manage_event_categories',
234
-            ),
235
-        );
236
-    }
237
-
238
-
239
-    /**
240
-     * Set the _page_config property for this admin page group.
241
-     */
242
-    protected function _set_page_config()
243
-    {
244
-        $this->_page_config = [
245
-            'default'                => [
246
-                'nav'           => [
247
-                    'label' => esc_html__('Overview', 'event_espresso'),
248
-                    'order' => 10,
249
-                ],
250
-                'list_table'    => 'Events_Admin_List_Table',
251
-                'help_tabs'     => [
252
-                    'events_overview_help_tab'                       => [
253
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
254
-                        'filename' => 'events_overview',
255
-                    ],
256
-                    'events_overview_table_column_headings_help_tab' => [
257
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
258
-                        'filename' => 'events_overview_table_column_headings',
259
-                    ],
260
-                    'events_overview_filters_help_tab'               => [
261
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
262
-                        'filename' => 'events_overview_filters',
263
-                    ],
264
-                    'events_overview_view_help_tab'                  => [
265
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
266
-                        'filename' => 'events_overview_views',
267
-                    ],
268
-                    'events_overview_other_help_tab'                 => [
269
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
270
-                        'filename' => 'events_overview_other',
271
-                    ],
272
-                ],
273
-                'help_tour'     => [
274
-                    'Event_Overview_Help_Tour',
275
-                    // 'New_Features_Test_Help_Tour' for testing multiple help tour
276
-                ],
277
-                'require_nonce' => false,
278
-                'qtips' => ['EE_Event_List_Table_Tips'],
279
-            ],
280
-            'create_new'             => [
281
-                'nav'           => [
282
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
283
-                    'order'      => 5,
284
-                    'persistent' => false,
285
-                ],
286
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
287
-                'help_tabs'     => [
288
-                    'event_editor_help_tab'                            => [
289
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
290
-                        'filename' => 'event_editor',
291
-                    ],
292
-                    'event_editor_title_richtexteditor_help_tab'       => [
293
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
294
-                        'filename' => 'event_editor_title_richtexteditor',
295
-                    ],
296
-                    'event_editor_venue_details_help_tab'              => [
297
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
298
-                        'filename' => 'event_editor_venue_details',
299
-                    ],
300
-                    'event_editor_event_datetimes_help_tab'            => [
301
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
302
-                        'filename' => 'event_editor_event_datetimes',
303
-                    ],
304
-                    'event_editor_event_tickets_help_tab'              => [
305
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
306
-                        'filename' => 'event_editor_event_tickets',
307
-                    ],
308
-                    'event_editor_event_registration_options_help_tab' => [
309
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
310
-                        'filename' => 'event_editor_event_registration_options',
311
-                    ],
312
-                    'event_editor_tags_categories_help_tab'            => [
313
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
314
-                        'filename' => 'event_editor_tags_categories',
315
-                    ],
316
-                    'event_editor_questions_registrants_help_tab'      => [
317
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
318
-                        'filename' => 'event_editor_questions_registrants',
319
-                    ],
320
-                    'event_editor_save_new_event_help_tab'             => [
321
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
322
-                        'filename' => 'event_editor_save_new_event',
323
-                    ],
324
-                    'event_editor_other_help_tab'                      => [
325
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
326
-                        'filename' => 'event_editor_other',
327
-                    ],
328
-                ],
329
-                'help_tour'     => [
330
-                    'Event_Editor_Help_Tour',
331
-                ],
332
-                'require_nonce' => false,
333
-            ],
334
-            'edit'                   => [
335
-                'nav'           => [
336
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
337
-                    'order'      => 5,
338
-                    'persistent' => false,
339
-                    'url'        => isset($this->_req_data['post'])
340
-                        ? EE_Admin_Page::add_query_args_and_nonce(
341
-                            ['post' => $this->_req_data['post'], 'action' => 'edit'],
342
-                            $this->_current_page_view_url
343
-                        )
344
-                        : $this->_admin_base_url,
345
-                ],
346
-                'metaboxes'     => ['_register_event_editor_meta_boxes'],
347
-                'help_tabs'     => [
348
-                    'event_editor_help_tab'                            => [
349
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
350
-                        'filename' => 'event_editor',
351
-                    ],
352
-                    'event_editor_title_richtexteditor_help_tab'       => [
353
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
354
-                        'filename' => 'event_editor_title_richtexteditor',
355
-                    ],
356
-                    'event_editor_venue_details_help_tab'              => [
357
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
358
-                        'filename' => 'event_editor_venue_details',
359
-                    ],
360
-                    'event_editor_event_datetimes_help_tab'            => [
361
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
362
-                        'filename' => 'event_editor_event_datetimes',
363
-                    ],
364
-                    'event_editor_event_tickets_help_tab'              => [
365
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
366
-                        'filename' => 'event_editor_event_tickets',
367
-                    ],
368
-                    'event_editor_event_registration_options_help_tab' => [
369
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
370
-                        'filename' => 'event_editor_event_registration_options',
371
-                    ],
372
-                    'event_editor_tags_categories_help_tab'            => [
373
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
374
-                        'filename' => 'event_editor_tags_categories',
375
-                    ],
376
-                    'event_editor_questions_registrants_help_tab'      => [
377
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
378
-                        'filename' => 'event_editor_questions_registrants',
379
-                    ],
380
-                    'event_editor_save_new_event_help_tab'             => [
381
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
382
-                        'filename' => 'event_editor_save_new_event',
383
-                    ],
384
-                    'event_editor_other_help_tab'                      => [
385
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
386
-                        'filename' => 'event_editor_other',
387
-                    ],
388
-                ],
389
-                'require_nonce' => false,
390
-            ],
391
-            'default_event_settings' => [
392
-                'nav'           => [
393
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
394
-                    'order' => 40,
395
-                ],
396
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
397
-                'labels'        => [
398
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
399
-                ],
400
-                'help_tabs'     => [
401
-                    'default_settings_help_tab'        => [
402
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
403
-                        'filename' => 'events_default_settings',
404
-                    ],
405
-                    'default_settings_status_help_tab' => [
406
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
407
-                        'filename' => 'events_default_settings_status',
408
-                    ],
409
-                    'default_maximum_tickets_help_tab' => [
410
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
411
-                        'filename' => 'events_default_settings_max_tickets',
412
-                    ],
413
-                ],
414
-                'help_tour'     => ['Event_Default_Settings_Help_Tour'],
415
-                'require_nonce' => false,
416
-            ],
417
-            // template settings
418
-            'template_settings'      => [
419
-                'nav'           => [
420
-                    'label' => esc_html__('Templates', 'event_espresso'),
421
-                    'order' => 30,
422
-                ],
423
-                'metaboxes'     => $this->_default_espresso_metaboxes,
424
-                'help_tabs'     => [
425
-                    'general_settings_templates_help_tab' => [
426
-                        'title'    => esc_html__('Templates', 'event_espresso'),
427
-                        'filename' => 'general_settings_templates',
428
-                    ],
429
-                ],
430
-                'help_tour'     => ['Templates_Help_Tour'],
431
-                'require_nonce' => false,
432
-            ],
433
-            // event category stuff
434
-            'add_category'           => [
435
-                'nav'           => [
436
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
437
-                    'order'      => 15,
438
-                    'persistent' => false,
439
-                ],
440
-                'help_tabs'     => [
441
-                    'add_category_help_tab' => [
442
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
443
-                        'filename' => 'events_add_category',
444
-                    ],
445
-                ],
446
-                'help_tour'     => ['Event_Add_Category_Help_Tour'],
447
-                'metaboxes'     => ['_publish_post_box'],
448
-                'require_nonce' => false,
449
-            ],
450
-            'edit_category'          => [
451
-                'nav'           => [
452
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
453
-                    'order'      => 15,
454
-                    'persistent' => false,
455
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
456
-                        ? add_query_arg(
457
-                            ['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
458
-                            $this->_current_page_view_url
459
-                        )
460
-                        : $this->_admin_base_url,
461
-                ],
462
-                'help_tabs'     => [
463
-                    'edit_category_help_tab' => [
464
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
465
-                        'filename' => 'events_edit_category',
466
-                    ],
467
-                ],
468
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
469
-                'metaboxes'     => ['_publish_post_box'],
470
-                'require_nonce' => false,
471
-            ],
472
-            'category_list'          => [
473
-                'nav'           => [
474
-                    'label' => esc_html__('Categories', 'event_espresso'),
475
-                    'order' => 20,
476
-                ],
477
-                'list_table'    => 'Event_Categories_Admin_List_Table',
478
-                'help_tabs'     => [
479
-                    'events_categories_help_tab'                       => [
480
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
481
-                        'filename' => 'events_categories',
482
-                    ],
483
-                    'events_categories_table_column_headings_help_tab' => [
484
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
485
-                        'filename' => 'events_categories_table_column_headings',
486
-                    ],
487
-                    'events_categories_view_help_tab'                  => [
488
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
489
-                        'filename' => 'events_categories_views',
490
-                    ],
491
-                    'events_categories_other_help_tab'                 => [
492
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
493
-                        'filename' => 'events_categories_other',
494
-                    ],
495
-                ],
496
-                'help_tour'     => [
497
-                    'Event_Categories_Help_Tour',
498
-                ],
499
-                'metaboxes'     => $this->_default_espresso_metaboxes,
500
-                'require_nonce' => false,
501
-            ],
502
-        ];
503
-        // only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
504
-        $domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
505
-        if (! $domain->isCaffeinated()) {
506
-            $this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
507
-            $this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips' ];
508
-        }
509
-    }
510
-
511
-
512
-    /**
513
-     * Used to register any global screen options if necessary for every route in this admin page group.
514
-     */
515
-    protected function _add_screen_options()
516
-    {
517
-    }
518
-
519
-
520
-    /**
521
-     * Implementing the screen options for the 'default' route.
522
-     *
523
-     * @throws InvalidArgumentException
524
-     * @throws InvalidDataTypeException
525
-     * @throws InvalidInterfaceException
526
-     */
527
-    protected function _add_screen_options_default()
528
-    {
529
-        $this->_per_page_screen_option();
530
-    }
531
-
532
-
533
-    /**
534
-     * Implementing screen options for the category list route.
535
-     *
536
-     * @throws InvalidArgumentException
537
-     * @throws InvalidDataTypeException
538
-     * @throws InvalidInterfaceException
539
-     */
540
-    protected function _add_screen_options_category_list()
541
-    {
542
-        $page_title = $this->_admin_page_title;
543
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
544
-        $this->_per_page_screen_option();
545
-        $this->_admin_page_title = $page_title;
546
-    }
547
-
548
-
549
-    /**
550
-     * Used to register any global feature pointers for the admin page group.
551
-     */
552
-    protected function _add_feature_pointers()
553
-    {
554
-    }
555
-
556
-
557
-    /**
558
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
559
-     */
560
-    public function load_scripts_styles()
561
-    {
562
-        wp_register_style(
563
-            'events-admin-css',
564
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
565
-            [],
566
-            EVENT_ESPRESSO_VERSION
567
-        );
568
-        wp_register_style(
569
-            'ee-cat-admin',
570
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
571
-            [],
572
-            EVENT_ESPRESSO_VERSION
573
-        );
574
-        wp_enqueue_style('events-admin-css');
575
-        wp_enqueue_style('ee-cat-admin');
576
-        // scripts
577
-        wp_register_script(
578
-            'event_editor_js',
579
-            EVENTS_ASSETS_URL . 'event_editor.js',
580
-            ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
581
-            EVENT_ESPRESSO_VERSION,
582
-            true
583
-        );
584
-    }
585
-
586
-
587
-    /**
588
-     * Enqueuing scripts and styles specific to this view
589
-     */
590
-    public function load_scripts_styles_create_new()
591
-    {
592
-        $this->load_scripts_styles_edit();
593
-    }
594
-
595
-
596
-    /**
597
-     * Enqueuing scripts and styles specific to this view
598
-     */
599
-    public function load_scripts_styles_edit()
600
-    {
601
-        // styles
602
-        wp_enqueue_style('espresso-ui-theme');
603
-        wp_register_style(
604
-            'event-editor-css',
605
-            EVENTS_ASSETS_URL . 'event-editor.css',
606
-            ['ee-admin-css'],
607
-            EVENT_ESPRESSO_VERSION
608
-        );
609
-        wp_enqueue_style('event-editor-css');
610
-        // scripts
611
-        if (! $this->admin_config->useAdvancedEditor()) {
612
-            wp_register_script(
613
-                'event-datetime-metabox',
614
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
615
-                ['event_editor_js', 'ee-datepicker'],
616
-                EVENT_ESPRESSO_VERSION
617
-            );
618
-            wp_enqueue_script('event-datetime-metabox');
619
-        }
620
-    }
621
-
622
-
623
-    /**
624
-     * Populating the _views property for the category list table view.
625
-     */
626
-    protected function _set_list_table_views_category_list()
627
-    {
628
-        $this->_views = array(
629
-            'all' => array(
630
-                'slug'        => 'all',
631
-                'label'       => esc_html__('All', 'event_espresso'),
632
-                'count'       => 0,
633
-                'bulk_action' => array(
634
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
635
-                ),
636
-            ),
637
-        );
638
-    }
639
-
640
-
641
-    /**
642
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
643
-     */
644
-    public function admin_init()
645
-    {
646
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
647
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
648
-            'event_espresso'
649
-        );
650
-    }
651
-
652
-
653
-    /**
654
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
655
-     * group.
656
-     */
657
-    public function admin_notices()
658
-    {
659
-    }
660
-
661
-
662
-    /**
663
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
664
-     * this admin page group.
665
-     */
666
-    public function admin_footer_scripts()
667
-    {
668
-    }
669
-
670
-
671
-    /**
672
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
673
-     * warning (via EE_Error::add_error());
674
-     *
675
-     * @param  EE_Event $event Event object
676
-     * @param string    $req_type
677
-     * @return void
678
-     * @throws EE_Error
679
-     * @access public
680
-     */
681
-    public function verify_event_edit($event = null, $req_type = '')
682
-    {
683
-        // don't need to do this when processing
684
-        if (! empty($req_type)) {
685
-            return;
686
-        }
687
-        // no event?
688
-        if (! $event instanceof EE_Event) {
689
-            $event = $this->_cpt_model_obj;
690
-        }
691
-        // STILL no event?
692
-        if (! $event instanceof EE_Event) {
693
-            return;
694
-        }
695
-        $orig_status = $event->status();
696
-        // first check if event is active.
697
-        if ($orig_status === EEM_Event::cancelled
698
-            || $orig_status === EEM_Event::postponed
699
-            || $event->is_expired()
700
-            || $event->is_inactive()
701
-        ) {
702
-            return;
703
-        }
704
-        // made it here so it IS active... next check that any of the tickets are sold.
705
-        if ($event->is_sold_out(true)) {
706
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
707
-                EE_Error::add_attention(
708
-                    sprintf(
709
-                        esc_html__(
710
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
711
-                            'event_espresso'
712
-                        ),
713
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
714
-                    )
715
-                );
716
-            }
717
-            return;
718
-        }
719
-        if ($orig_status === EEM_Event::sold_out) {
720
-            EE_Error::add_attention(
721
-                sprintf(
722
-                    esc_html__(
723
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
724
-                        'event_espresso'
725
-                    ),
726
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
727
-                )
728
-            );
729
-        }
730
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
731
-        if (! $event->tickets_on_sale()) {
732
-            return;
733
-        }
734
-        // made it here so show warning
735
-        $this->_edit_event_warning();
736
-    }
737
-
738
-
739
-    /**
740
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
741
-     * When needed, hook this into a EE_Error::add_error() notice.
742
-     *
743
-     * @access protected
744
-     * @return void
745
-     */
746
-    protected function _edit_event_warning()
747
-    {
748
-        // we don't want to add warnings during these requests
749
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
750
-            return;
751
-        }
752
-        EE_Error::add_attention(
753
-            sprintf(
754
-                esc_html__(
755
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
756
-                    'event_espresso'
757
-                ),
758
-                '<a class="espresso-help-tab-lnk">',
759
-                '</a>'
760
-            )
761
-        );
762
-    }
763
-
764
-
765
-    /**
766
-     * When a user is creating a new event, notify them if they haven't set their timezone.
767
-     * Otherwise, do the normal logic
768
-     *
769
-     * @return string
770
-     * @throws EE_Error
771
-     * @throws InvalidArgumentException
772
-     * @throws InvalidDataTypeException
773
-     * @throws InvalidInterfaceException
774
-     */
775
-    protected function _create_new_cpt_item()
776
-    {
777
-        $has_timezone_string = get_option('timezone_string');
778
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
779
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
780
-            EE_Error::add_attention(
781
-                sprintf(
782
-                    __(
783
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
784
-                        'event_espresso'
785
-                    ),
786
-                    '<br>',
787
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
788
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
789
-                    . '</select>',
790
-                    '<button class="button button-secondary timezone-submit">',
791
-                    '</button><span class="spinner"></span>'
792
-                ),
793
-                __FILE__,
794
-                __FUNCTION__,
795
-                __LINE__
796
-            );
797
-        }
798
-        parent::_create_new_cpt_item();
799
-    }
800
-
801
-
802
-    /**
803
-     * Sets the _views property for the default route in this admin page group.
804
-     */
805
-    protected function _set_list_table_views_default()
806
-    {
807
-        $this->_views = array(
808
-            'all'   => array(
809
-                'slug'        => 'all',
810
-                'label'       => esc_html__('View All Events', 'event_espresso'),
811
-                'count'       => 0,
812
-                'bulk_action' => array(
813
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
814
-                ),
815
-            ),
816
-            'draft' => array(
817
-                'slug'        => 'draft',
818
-                'label'       => esc_html__('Draft', 'event_espresso'),
819
-                'count'       => 0,
820
-                'bulk_action' => array(
821
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
822
-                ),
823
-            ),
824
-        );
825
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
826
-            $this->_views['trash'] = array(
827
-                'slug'        => 'trash',
828
-                'label'       => esc_html__('Trash', 'event_espresso'),
829
-                'count'       => 0,
830
-                'bulk_action' => array(
831
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
832
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
833
-                ),
834
-            );
835
-        }
836
-    }
837
-
838
-
839
-    /**
840
-     * Provides the legend item array for the default list table view.
841
-     *
842
-     * @return array
843
-     */
844
-    protected function _event_legend_items()
845
-    {
846
-        $items = array(
847
-            'view_details'   => array(
848
-                'class' => 'dashicons dashicons-search',
849
-                'desc'  => esc_html__('View Event', 'event_espresso'),
850
-            ),
851
-            'edit_event'     => array(
852
-                'class' => 'ee-icon ee-icon-calendar-edit',
853
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
854
-            ),
855
-            'view_attendees' => array(
856
-                'class' => 'dashicons dashicons-groups',
857
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
858
-            ),
859
-        );
860
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
861
-        $statuses = array(
862
-            'sold_out_status'  => array(
863
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
864
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
865
-            ),
866
-            'active_status'    => array(
867
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
868
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
869
-            ),
870
-            'upcoming_status'  => array(
871
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
872
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
873
-            ),
874
-            'postponed_status' => array(
875
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
876
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
877
-            ),
878
-            'cancelled_status' => array(
879
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
880
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
881
-            ),
882
-            'expired_status'   => array(
883
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
884
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
885
-            ),
886
-            'inactive_status'  => array(
887
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
888
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
889
-            ),
890
-        );
891
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
892
-        return array_merge($items, $statuses);
893
-    }
894
-
895
-
896
-    /**
897
-     * @return EEM_Event
898
-     * @throws EE_Error
899
-     * @throws InvalidArgumentException
900
-     * @throws InvalidDataTypeException
901
-     * @throws InvalidInterfaceException
902
-     * @throws ReflectionException
903
-     */
904
-    private function _event_model()
905
-    {
906
-        if (! $this->_event_model instanceof EEM_Event) {
907
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
908
-        }
909
-        return $this->_event_model;
910
-    }
911
-
912
-
913
-    /**
914
-     * Adds extra buttons to the WP CPT permalink field row.
915
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
916
-     *
917
-     * @param  string $return    the current html
918
-     * @param  int    $id        the post id for the page
919
-     * @param  string $new_title What the title is
920
-     * @param  string $new_slug  what the slug is
921
-     * @return string            The new html string for the permalink area
922
-     */
923
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
924
-    {
925
-        // make sure this is only when editing
926
-        if (! empty($id)) {
927
-            $post = get_post($id);
928
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
929
-                       . esc_html__('Shortcode', 'event_espresso')
930
-                       . '</a> ';
931
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
932
-                       . $post->ID
933
-                       . ']">';
934
-        }
935
-        return $return;
936
-    }
937
-
938
-
939
-    /**
940
-     * _events_overview_list_table
941
-     * This contains the logic for showing the events_overview list
942
-     *
943
-     * @access protected
944
-     * @return void
945
-     * @throws DomainException
946
-     * @throws EE_Error
947
-     * @throws InvalidArgumentException
948
-     * @throws InvalidDataTypeException
949
-     * @throws InvalidInterfaceException
950
-     */
951
-    protected function _events_overview_list_table()
952
-    {
953
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
954
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
955
-            ? (array) $this->_template_args['after_list_table']
956
-            : array();
957
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
958
-                . EEH_Template::get_button_or_link(
959
-                    get_post_type_archive_link('espresso_events'),
960
-                    esc_html__('View Event Archive Page', 'event_espresso'),
961
-                    'button'
962
-                );
963
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
964
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
965
-            'create_new',
966
-            'add',
967
-            array(),
968
-            'add-new-h2'
969
-        );
970
-        $this->display_admin_list_table_page_with_no_sidebar();
971
-    }
972
-
973
-
974
-    /**
975
-     * this allows for extra misc actions in the default WP publish box
976
-     *
977
-     * @return void
978
-     * @throws DomainException
979
-     * @throws EE_Error
980
-     * @throws InvalidArgumentException
981
-     * @throws InvalidDataTypeException
982
-     * @throws InvalidInterfaceException
983
-     * @throws ReflectionException
984
-     */
985
-    public function extra_misc_actions_publish_box()
986
-    {
987
-        $this->_generate_publish_box_extra_content();
988
-    }
989
-
990
-
991
-    /**
992
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
993
-     * saved.
994
-     * Typically you would use this to save any additional data.
995
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
996
-     * ALSO very important.  When a post transitions from scheduled to published,
997
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
998
-     * other meta saves. So MAKE sure that you handle this accordingly.
999
-     *
1000
-     * @access protected
1001
-     * @abstract
1002
-     * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1003
-     * @param object $post    The post object of the cpt that was saved.
1004
-     * @return void
1005
-     * @throws EE_Error
1006
-     * @throws InvalidArgumentException
1007
-     * @throws InvalidDataTypeException
1008
-     * @throws InvalidInterfaceException
1009
-     * @throws ReflectionException
1010
-     */
1011
-    protected function _insert_update_cpt_item($post_id, $post)
1012
-    {
1013
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1014
-            // get out we're not processing an event save.
1015
-            return;
1016
-        }
1017
-        $event_values = array(
1018
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1019
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1020
-            'EVT_additional_limit'            => min(
1021
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1022
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1023
-            ),
1024
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1025
-                ? $this->_req_data['EVT_default_registration_status']
1026
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
1027
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1028
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1029
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1030
-                ? $this->_req_data['timezone_string'] : null,
1031
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1032
-                ? $this->_req_data['externalURL'] : null,
1033
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1034
-                ? $this->_req_data['event_phone'] : null,
1035
-        );
1036
-        // update event
1037
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1038
-        // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1039
-        $get_one_where = array(
1040
-            $this->_event_model()->primary_key_name() => $post_id,
1041
-            'OR'                                      => array(
1042
-                'status'   => $post->post_status,
1043
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1044
-                // but the returned object here has a status of "publish", so use the original post status as well
1045
-                'status*1' => $this->_req_data['original_post_status'],
1046
-            ),
1047
-        );
1048
-        $event = $this->_event_model()->get_one(array($get_one_where));
1049
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1050
-        $event_update_callbacks = apply_filters(
1051
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1052
-            array(
1053
-                array($this, '_default_venue_update'),
1054
-                array($this, '_default_tickets_update'),
1055
-            )
1056
-        );
1057
-        $att_success = true;
1058
-        foreach ($event_update_callbacks as $e_callback) {
1059
-            $_success = is_callable($e_callback)
1060
-                ? $e_callback($event, $this->_req_data)
1061
-                : false;
1062
-            // if ANY of these updates fail then we want the appropriate global error message
1063
-            $att_success = ! $att_success ? $att_success : $_success;
1064
-        }
1065
-        // any errors?
1066
-        if ($success && false === $att_success) {
1067
-            EE_Error::add_error(
1068
-                esc_html__(
1069
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1070
-                    'event_espresso'
1071
-                ),
1072
-                __FILE__,
1073
-                __FUNCTION__,
1074
-                __LINE__
1075
-            );
1076
-        } elseif ($success === false) {
1077
-            EE_Error::add_error(
1078
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1079
-                __FILE__,
1080
-                __FUNCTION__,
1081
-                __LINE__
1082
-            );
1083
-        }
1084
-    }
1085
-
1086
-
1087
-    /**
1088
-     * @param int $post_id
1089
-     * @param int $revision_id
1090
-     * @throws EE_Error
1091
-     * @throws InvalidArgumentException
1092
-     * @throws InvalidDataTypeException
1093
-     * @throws InvalidInterfaceException
1094
-     * @throws ReflectionException
1095
-     * @see parent::restore_item()
1096
-     */
1097
-    protected function _restore_cpt_item($post_id, $revision_id)
1098
-    {
1099
-        // copy existing event meta to new post
1100
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1101
-        if ($post_evt instanceof EE_Event) {
1102
-            // meta revision restore
1103
-            $post_evt->restore_revision($revision_id);
1104
-            // related objs restore
1105
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1106
-        }
1107
-    }
1108
-
1109
-
1110
-    /**
1111
-     * Attach the venue to the Event
1112
-     *
1113
-     * @param EE_Event $evtobj Event Object to add the venue to
1114
-     * @param array    $data   The request data from the form
1115
-     * @return bool           Success or fail.
1116
-     * @throws EE_Error
1117
-     * @throws InvalidArgumentException
1118
-     * @throws InvalidDataTypeException
1119
-     * @throws InvalidInterfaceException
1120
-     * @throws ReflectionException
1121
-     */
1122
-    protected function _default_venue_update(EE_Event $evtobj, $data)
1123
-    {
1124
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1125
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1126
-        $rows_affected = null;
1127
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1128
-        // very important.  If we don't have a venue name...
1129
-        // then we'll get out because not necessary to create empty venue
1130
-        if (empty($data['venue_title'])) {
1131
-            return false;
1132
-        }
1133
-        $venue_array = array(
1134
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1135
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1136
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1137
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1138
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1139
-                : null,
1140
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1141
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1142
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1143
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1144
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1145
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1146
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1147
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1148
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1149
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1150
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1151
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1152
-            'status'              => 'publish',
1153
-        );
1154
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1155
-        if (! empty($venue_id)) {
1156
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1157
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1158
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1159
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1160
-            return $rows_affected > 0;
1161
-        }
1162
-        // we insert the venue
1163
-        $venue_id = $venue_model->insert($venue_array);
1164
-        $evtobj->_add_relation_to($venue_id, 'Venue');
1165
-        return ! empty($venue_id) ? true : false;
1166
-        // when we have the ancestor come in it's already been handled by the revision save.
1167
-    }
1168
-
1169
-
1170
-    /**
1171
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1172
-     *
1173
-     * @param EE_Event $evtobj The Event object we're attaching data to
1174
-     * @param array    $data   The request data from the form
1175
-     * @return array
1176
-     * @throws EE_Error
1177
-     * @throws InvalidArgumentException
1178
-     * @throws InvalidDataTypeException
1179
-     * @throws InvalidInterfaceException
1180
-     * @throws ReflectionException
1181
-     * @throws Exception
1182
-     */
1183
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1184
-    {
1185
-        if ($this->admin_config->useAdvancedEditor()) {
1186
-            return [];
1187
-        }
1188
-        $success = true;
1189
-        $saved_dtt = null;
1190
-        $saved_tickets = array();
1191
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1192
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1193
-            // trim all values to ensure any excess whitespace is removed.
1194
-            $dtt = array_map('trim', $dtt);
1195
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1196
-                : $dtt['DTT_EVT_start'];
1197
-            $datetime_values = array(
1198
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1199
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1200
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1201
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1202
-                'DTT_order'     => $row,
1203
-            );
1204
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1205
-            if (! empty($dtt['DTT_ID'])) {
1206
-                $DTM = EE_Registry::instance()
1207
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1208
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1209
-                $DTM->set_date_format($incoming_date_formats[0]);
1210
-                $DTM->set_time_format($incoming_date_formats[1]);
1211
-                foreach ($datetime_values as $field => $value) {
1212
-                    $DTM->set($field, $value);
1213
-                }
1214
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1215
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1216
-            } else {
1217
-                $DTM = EE_Registry::instance()->load_class(
1218
-                    'Datetime',
1219
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1220
-                    false,
1221
-                    false
1222
-                );
1223
-                foreach ($datetime_values as $field => $value) {
1224
-                    $DTM->set($field, $value);
1225
-                }
1226
-            }
1227
-            $DTM->save();
1228
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1229
-            // load DTT helper
1230
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1231
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1232
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1233
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1234
-                $DTT->save();
1235
-            }
1236
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1237
-            $saved_dtt = $DTT;
1238
-            $success = ! $success ? $success : $DTT;
1239
-            // if ANY of these updates fail then we want the appropriate global error message.
1240
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1241
-        }
1242
-        // no dtts get deleted so we don't do any of that logic here.
1243
-        // update tickets next
1244
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1245
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1246
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1247
-            $update_prices = false;
1248
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1249
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1250
-            // trim inputs to ensure any excess whitespace is removed.
1251
-            $tkt = array_map('trim', $tkt);
1252
-            if (empty($tkt['TKT_start_date'])) {
1253
-                // let's use now in the set timezone.
1254
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1255
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1256
-            }
1257
-            if (empty($tkt['TKT_end_date'])) {
1258
-                // use the start date of the first datetime
1259
-                $dtt = $evtobj->first_datetime();
1260
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1261
-                    $incoming_date_formats[0],
1262
-                    $incoming_date_formats[1]
1263
-                );
1264
-            }
1265
-            $TKT_values = array(
1266
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1267
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1268
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1269
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1270
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1271
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1272
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1273
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1274
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1275
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1276
-                'TKT_row'         => $row,
1277
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1278
-                'TKT_price'       => $ticket_price,
1279
-            );
1280
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1281
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1282
-                $TKT_values['TKT_ID'] = 0;
1283
-                $TKT_values['TKT_is_default'] = 0;
1284
-                $TKT_values['TKT_price'] = $ticket_price;
1285
-                $update_prices = true;
1286
-            }
1287
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1288
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1289
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1290
-            if (! empty($tkt['TKT_ID'])) {
1291
-                $TKT = EE_Registry::instance()
1292
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1293
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1294
-                if ($TKT instanceof EE_Ticket) {
1295
-                    $ticket_sold = $TKT->count_related(
1296
-                        'Registration',
1297
-                        array(
1298
-                            array(
1299
-                                'STS_ID' => array(
1300
-                                    'NOT IN',
1301
-                                    array(EEM_Registration::status_id_incomplete),
1302
-                                ),
1303
-                            ),
1304
-                        )
1305
-                    ) > 0;
1306
-                    // let's just check the total price for the existing ticket and determine if it matches the new
1307
-                    // total price.  if they are different then we create a new ticket (if tickets sold)
1308
-                    // if they aren't different then we go ahead and modify existing ticket.
1309
-                    $create_new_TKT = $ticket_sold && ! $TKT->deleted() && EEH_Money::compare_floats(
1310
-                        $ticket_price,
1311
-                        $TKT->get('TKT_price'),
1312
-                        '!=='
1313
-                    );
1314
-                    $TKT->set_date_format($incoming_date_formats[0]);
1315
-                    $TKT->set_time_format($incoming_date_formats[1]);
1316
-                    // set new values
1317
-                    foreach ($TKT_values as $field => $value) {
1318
-                        if ($field === 'TKT_qty') {
1319
-                            $TKT->set_qty($value);
1320
-                        } else {
1321
-                            $TKT->set($field, $value);
1322
-                        }
1323
-                    }
1324
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1325
-                    if ($create_new_TKT) {
1326
-                        // archive the old ticket first
1327
-                        $TKT->set('TKT_deleted', 1);
1328
-                        $TKT->save();
1329
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1330
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1331
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1332
-                        $TKT = clone $TKT;
1333
-                        $TKT->set('TKT_ID', 0);
1334
-                        $TKT->set('TKT_deleted', 0);
1335
-                        $TKT->set('TKT_price', $ticket_price);
1336
-                        $TKT->set('TKT_sold', 0);
1337
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1338
-                        $update_prices = true;
1339
-                    }
1340
-                    // make sure price is set if it hasn't been already
1341
-                    $TKT->set('TKT_price', $ticket_price);
1342
-                }
1343
-            } else {
1344
-                // no TKT_id so a new TKT
1345
-                $TKT_values['TKT_price'] = $ticket_price;
1346
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1347
-                if ($TKT instanceof EE_Ticket) {
1348
-                    // need to reset values to properly account for the date formats
1349
-                    $TKT->set_date_format($incoming_date_formats[0]);
1350
-                    $TKT->set_time_format($incoming_date_formats[1]);
1351
-                    $TKT->set_timezone($evtobj->get_timezone());
1352
-                    // set new values
1353
-                    foreach ($TKT_values as $field => $value) {
1354
-                        if ($field === 'TKT_qty') {
1355
-                            $TKT->set_qty($value);
1356
-                        } else {
1357
-                            $TKT->set($field, $value);
1358
-                        }
1359
-                    }
1360
-                    $update_prices = true;
1361
-                }
1362
-            }
1363
-            // cap ticket qty by datetime reg limits
1364
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1365
-            // update ticket.
1366
-            $TKT->save();
1367
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1368
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1369
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1370
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1371
-                $TKT->save();
1372
-            }
1373
-            // initially let's add the ticket to the dtt
1374
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1375
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1376
-            // add prices to ticket
1377
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1378
-        }
1379
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1380
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
1381
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1382
-        foreach ($tickets_removed as $id) {
1383
-            $id = absint($id);
1384
-            // get the ticket for this id
1385
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1386
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1387
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1388
-            foreach ($dtts as $dtt) {
1389
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1390
-            }
1391
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1392
-            $tkt_to_remove->delete_related_permanently('Price');
1393
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1394
-            $tkt_to_remove->delete_permanently();
1395
-        }
1396
-        return array($saved_dtt, $saved_tickets);
1397
-    }
1398
-
1399
-
1400
-    /**
1401
-     * This attaches a list of given prices to a ticket.
1402
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1403
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1404
-     * price info and prices are automatically "archived" via the ticket.
1405
-     *
1406
-     * @access  private
1407
-     * @param array     $prices     Array of prices from the form.
1408
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1409
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1410
-     * @return  void
1411
-     * @throws EE_Error
1412
-     * @throws InvalidArgumentException
1413
-     * @throws InvalidDataTypeException
1414
-     * @throws InvalidInterfaceException
1415
-     * @throws ReflectionException
1416
-     */
1417
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1418
-    {
1419
-        foreach ($prices as $row => $prc) {
1420
-            $PRC_values = array(
1421
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1422
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1423
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1424
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1425
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1426
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1427
-                'PRC_order'      => $row,
1428
-            );
1429
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1430
-                $PRC_values['PRC_ID'] = 0;
1431
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1432
-            } else {
1433
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1434
-                // update this price with new values
1435
-                foreach ($PRC_values as $field => $newprc) {
1436
-                    $PRC->set($field, $newprc);
1437
-                }
1438
-                $PRC->save();
1439
-            }
1440
-            $ticket->_add_relation_to($PRC, 'Price');
1441
-        }
1442
-    }
1443
-
1444
-
1445
-    /**
1446
-     * Add in our autosave ajax handlers
1447
-     *
1448
-     */
1449
-    protected function _ee_autosave_create_new()
1450
-    {
1451
-    }
1452
-
1453
-
1454
-    /**
1455
-     * More autosave handlers.
1456
-     */
1457
-    protected function _ee_autosave_edit()
1458
-    {
1459
-    }
1460
-
1461
-
1462
-    /**
1463
-     *    _generate_publish_box_extra_content
1464
-     *
1465
-     * @throws DomainException
1466
-     * @throws EE_Error
1467
-     * @throws InvalidArgumentException
1468
-     * @throws InvalidDataTypeException
1469
-     * @throws InvalidInterfaceException
1470
-     * @throws ReflectionException
1471
-     */
1472
-    private function _generate_publish_box_extra_content()
1473
-    {
1474
-        // load formatter helper
1475
-        // args for getting related registrations
1476
-        $approved_query_args = array(
1477
-            array(
1478
-                'REG_deleted' => 0,
1479
-                'STS_ID'      => EEM_Registration::status_id_approved,
1480
-            ),
1481
-        );
1482
-        $not_approved_query_args = array(
1483
-            array(
1484
-                'REG_deleted' => 0,
1485
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1486
-            ),
1487
-        );
1488
-        $pending_payment_query_args = array(
1489
-            array(
1490
-                'REG_deleted' => 0,
1491
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1492
-            ),
1493
-        );
1494
-        // publish box
1495
-        $publish_box_extra_args = array(
1496
-            'view_approved_reg_url'        => add_query_arg(
1497
-                array(
1498
-                    'action'      => 'default',
1499
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1500
-                    '_reg_status' => EEM_Registration::status_id_approved,
1501
-                ),
1502
-                REG_ADMIN_URL
1503
-            ),
1504
-            'view_not_approved_reg_url'    => add_query_arg(
1505
-                array(
1506
-                    'action'      => 'default',
1507
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1508
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1509
-                ),
1510
-                REG_ADMIN_URL
1511
-            ),
1512
-            'view_pending_payment_reg_url' => add_query_arg(
1513
-                array(
1514
-                    'action'      => 'default',
1515
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1516
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1517
-                ),
1518
-                REG_ADMIN_URL
1519
-            ),
1520
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1521
-                'Registration',
1522
-                $approved_query_args
1523
-            ),
1524
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1525
-                'Registration',
1526
-                $not_approved_query_args
1527
-            ),
1528
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1529
-                'Registration',
1530
-                $pending_payment_query_args
1531
-            ),
1532
-            'misc_pub_section_class'       => apply_filters(
1533
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1534
-                'misc-pub-section'
1535
-            ),
1536
-        );
1537
-        ob_start();
1538
-        do_action(
1539
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1540
-            $this->_cpt_model_obj
1541
-        );
1542
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1543
-        // load template
1544
-        EEH_Template::display_template(
1545
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1546
-            $publish_box_extra_args
1547
-        );
1548
-    }
1549
-
1550
-
1551
-    /**
1552
-     * @return EE_Event
1553
-     */
1554
-    public function get_event_object()
1555
-    {
1556
-        return $this->_cpt_model_obj;
1557
-    }
1558
-
1559
-
1560
-
1561
-
1562
-    /** METABOXES * */
1563
-    /**
1564
-     * _register_event_editor_meta_boxes
1565
-     * add all metaboxes related to the event_editor
1566
-     *
1567
-     * @return void
1568
-     * @throws EE_Error
1569
-     * @throws InvalidArgumentException
1570
-     * @throws InvalidDataTypeException
1571
-     * @throws InvalidInterfaceException
1572
-     * @throws ReflectionException
1573
-     */
1574
-    protected function _register_event_editor_meta_boxes()
1575
-    {
1576
-        $this->verify_cpt_object();
1577
-        if ($this->admin_config->useAdvancedEditor()) {
1578
-            add_action(
1579
-                'add_meta_boxes_espresso_events',
1580
-                function () {
1581
-                    global $current_screen;
1582
-                    remove_meta_box('authordiv', $current_screen, 'normal');
1583
-                },
1584
-                99
1585
-            );
1586
-            return;
1587
-        }
1588
-        add_meta_box(
1589
-            'espresso_event_editor_tickets',
1590
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1591
-            [$this, 'ticket_metabox'],
1592
-            $this->page_slug,
1593
-            'normal',
1594
-            'high'
1595
-        );
1596
-        add_meta_box(
1597
-            'espresso_event_editor_event_options',
1598
-            esc_html__('Event Registration Options', 'event_espresso'),
1599
-            array($this, 'registration_options_meta_box'),
1600
-            $this->page_slug,
1601
-            'side'
1602
-        );
1603
-        // NOTE: if you're looking for other metaboxes in here,
1604
-        // where a metabox has a related management page in the admin
1605
-        // you will find it setup in the related management page's "_Hooks" file.
1606
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1607
-    }
1608
-
1609
-
1610
-    /**
1611
-     * @throws DomainException
1612
-     * @throws EE_Error
1613
-     * @throws InvalidArgumentException
1614
-     * @throws InvalidDataTypeException
1615
-     * @throws InvalidInterfaceException
1616
-     * @throws ReflectionException
1617
-     */
1618
-    public function ticket_metabox()
1619
-    {
1620
-        $existing_datetime_ids = $existing_ticket_ids = array();
1621
-        // defaults for template args
1622
-        $template_args = array(
1623
-            'existing_datetime_ids'    => '',
1624
-            'event_datetime_help_link' => '',
1625
-            'ticket_options_help_link' => '',
1626
-            'time'                     => null,
1627
-            'ticket_rows'              => '',
1628
-            'existing_ticket_ids'      => '',
1629
-            'total_ticket_rows'        => 1,
1630
-            'ticket_js_structure'      => '',
1631
-            'trash_icon'               => 'ee-lock-icon',
1632
-            'disabled'                 => '',
1633
-        );
1634
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1635
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1636
-        /**
1637
-         * 1. Start with retrieving Datetimes
1638
-         * 2. Fore each datetime get related tickets
1639
-         * 3. For each ticket get related prices
1640
-         */
1641
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1642
-        /** @type EE_Datetime $first_datetime */
1643
-        $first_datetime = reset($times);
1644
-        // do we get related tickets?
1645
-        if ($first_datetime instanceof EE_Datetime
1646
-            && $first_datetime->ID() !== 0
1647
-        ) {
1648
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1649
-            $template_args['time'] = $first_datetime;
1650
-            $related_tickets = $first_datetime->tickets(
1651
-                array(
1652
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1653
-                    'default_where_conditions' => 'none',
1654
-                )
1655
-            );
1656
-            if (! empty($related_tickets)) {
1657
-                $template_args['total_ticket_rows'] = count($related_tickets);
1658
-                $row = 0;
1659
-                foreach ($related_tickets as $ticket) {
1660
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1661
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1662
-                    $row++;
1663
-                }
1664
-            } else {
1665
-                $template_args['total_ticket_rows'] = 1;
1666
-                /** @type EE_Ticket $ticket */
1667
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1668
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1669
-            }
1670
-        } else {
1671
-            $template_args['time'] = $times[0];
1672
-            /** @type EE_Ticket $ticket */
1673
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1674
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1675
-            // NOTE: we're just sending the first default row
1676
-            // (decaf can't manage default tickets so this should be sufficient);
1677
-        }
1678
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1679
-            'event_editor_event_datetimes_help_tab'
1680
-        );
1681
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1682
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1683
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1684
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1685
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1686
-            true
1687
-        );
1688
-        $template = apply_filters(
1689
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1690
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1691
-        );
1692
-        EEH_Template::display_template($template, $template_args);
1693
-    }
1694
-
1695
-
1696
-    /**
1697
-     * Setup an individual ticket form for the decaf event editor page
1698
-     *
1699
-     * @access private
1700
-     * @param EE_Ticket $ticket   the ticket object
1701
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1702
-     * @param int       $row
1703
-     * @return string generated html for the ticket row.
1704
-     * @throws DomainException
1705
-     * @throws EE_Error
1706
-     * @throws InvalidArgumentException
1707
-     * @throws InvalidDataTypeException
1708
-     * @throws InvalidInterfaceException
1709
-     * @throws ReflectionException
1710
-     */
1711
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1712
-    {
1713
-        $template_args = array(
1714
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1715
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1716
-                : '',
1717
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1718
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1719
-            'TKT_name'            => $ticket->get('TKT_name'),
1720
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1721
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1722
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1723
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1724
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1725
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1726
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1727
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1728
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1729
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1730
-                : ' disabled=disabled',
1731
-        );
1732
-        $price = $ticket->ID() !== 0
1733
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1734
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1735
-        $price_args = array(
1736
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1737
-            'PRC_amount'            => $price->get('PRC_amount'),
1738
-            'PRT_ID'                => $price->get('PRT_ID'),
1739
-            'PRC_ID'                => $price->get('PRC_ID'),
1740
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1741
-        );
1742
-        // make sure we have default start and end dates if skeleton
1743
-        // handle rows that should NOT be empty
1744
-        if (empty($template_args['TKT_start_date'])) {
1745
-            // if empty then the start date will be now.
1746
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1747
-        }
1748
-        if (empty($template_args['TKT_end_date'])) {
1749
-            // get the earliest datetime (if present);
1750
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1751
-                ? $this->_cpt_model_obj->get_first_related(
1752
-                    'Datetime',
1753
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1754
-                )
1755
-                : null;
1756
-            if (! empty($earliest_dtt)) {
1757
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1758
-            } else {
1759
-                $template_args['TKT_end_date'] = date(
1760
-                    'Y-m-d h:i a',
1761
-                    mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1762
-                );
1763
-            }
1764
-        }
1765
-        $template_args = array_merge($template_args, $price_args);
1766
-        $template = apply_filters(
1767
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1768
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1769
-            $ticket
1770
-        );
1771
-        return EEH_Template::display_template($template, $template_args, true);
1772
-    }
1773
-
1774
-
1775
-    /**
1776
-     * @throws DomainException
1777
-     * @throws EE_Error
1778
-     */
1779
-    public function registration_options_meta_box()
1780
-    {
1781
-        $yes_no_values = array(
1782
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1783
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1784
-        );
1785
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1786
-            array(
1787
-                EEM_Registration::status_id_cancelled,
1788
-                EEM_Registration::status_id_declined,
1789
-                EEM_Registration::status_id_incomplete,
1790
-            ),
1791
-            true
1792
-        );
1793
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1794
-        $template_args['_event'] = $this->_cpt_model_obj;
1795
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1796
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1797
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1798
-            'default_reg_status',
1799
-            $default_reg_status_values,
1800
-            $this->_cpt_model_obj->default_registration_status()
1801
-        );
1802
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1803
-            'display_desc',
1804
-            $yes_no_values,
1805
-            $this->_cpt_model_obj->display_description()
1806
-        );
1807
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1808
-            'display_ticket_selector',
1809
-            $yes_no_values,
1810
-            $this->_cpt_model_obj->display_ticket_selector(),
1811
-            '',
1812
-            '',
1813
-            false
1814
-        );
1815
-        $template_args['additional_registration_options'] = apply_filters(
1816
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1817
-            '',
1818
-            $template_args,
1819
-            $yes_no_values,
1820
-            $default_reg_status_values
1821
-        );
1822
-        EEH_Template::display_template(
1823
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1824
-            $template_args
1825
-        );
1826
-    }
1827
-
1828
-
1829
-    /**
1830
-     * _get_events()
1831
-     * This method simply returns all the events (for the given _view and paging)
1832
-     *
1833
-     * @access public
1834
-     * @param int  $per_page     count of items per page (20 default);
1835
-     * @param int  $current_page what is the current page being viewed.
1836
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1837
-     *                           If FALSE then we return an array of event objects
1838
-     *                           that match the given _view and paging parameters.
1839
-     * @return array an array of event objects.
1840
-     * @throws EE_Error
1841
-     * @throws InvalidArgumentException
1842
-     * @throws InvalidDataTypeException
1843
-     * @throws InvalidInterfaceException
1844
-     * @throws ReflectionException
1845
-     * @throws Exception
1846
-     * @throws Exception
1847
-     * @throws Exception
1848
-     */
1849
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1850
-    {
1851
-        $EEME = $this->_event_model();
1852
-        $offset = ($current_page - 1) * $per_page;
1853
-        $limit = $count ? null : $offset . ',' . $per_page;
1854
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1855
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1856
-        if (isset($this->_req_data['month_range'])) {
1857
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1858
-            // simulate the FIRST day of the month, that fixes issues for months like February
1859
-            // where PHP doesn't know what to assume for date.
1860
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1861
-            $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1862
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1863
-        }
1864
-        $where = array();
1865
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1866
-        // determine what post_status our condition will have for the query.
1867
-        switch ($status) {
1868
-            case 'month':
1869
-            case 'today':
1870
-            case null:
1871
-            case 'all':
1872
-                break;
1873
-            case 'draft':
1874
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1875
-                break;
1876
-            default:
1877
-                $where['status'] = $status;
1878
-        }
1879
-        // categories?
1880
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1881
-            ? $this->_req_data['EVT_CAT'] : null;
1882
-        if (! empty($category)) {
1883
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1884
-            $where['Term_Taxonomy.term_id'] = $category;
1885
-        }
1886
-        // date where conditions
1887
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1888
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1889
-            $DateTime = new DateTime(
1890
-                $year_r . '-' . $month_r . '-01 00:00:00',
1891
-                new DateTimeZone('UTC')
1892
-            );
1893
-            $start = $DateTime->getTimestamp();
1894
-            // set the datetime to be the end of the month
1895
-            $DateTime->setDate(
1896
-                $year_r,
1897
-                $month_r,
1898
-                $DateTime->format('t')
1899
-            )->setTime(23, 59, 59);
1900
-            $end = $DateTime->getTimestamp();
1901
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1902
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1903
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1904
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1905
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1906
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1907
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1908
-            $now = date('Y-m-01');
1909
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1910
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1911
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1912
-                            ->setTime(23, 59, 59)
1913
-                            ->format(implode(' ', $start_formats));
1914
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1915
-        }
1916
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1917
-            $where['EVT_wp_user'] = get_current_user_id();
1918
-        } elseif (! isset($where['status'])
1919
-            && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1920
-        ) {
1921
-            $where['OR'] = array(
1922
-                'status*restrict_private' => array('!=', 'private'),
1923
-                'AND'                     => array(
1924
-                    'status*inclusive' => array('=', 'private'),
1925
-                    'EVT_wp_user'      => get_current_user_id(),
1926
-                ),
1927
-            );
1928
-        }
1929
-
1930
-        if (isset($this->_req_data['EVT_wp_user'])
1931
-            && (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
1932
-            && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1933
-        ) {
1934
-            $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1935
-        }
1936
-        // search query handling
1937
-        if (isset($this->_req_data['s'])) {
1938
-            $search_string = '%' . $this->_req_data['s'] . '%';
1939
-            $where['OR'] = array(
1940
-                'EVT_name'       => array('LIKE', $search_string),
1941
-                'EVT_desc'       => array('LIKE', $search_string),
1942
-                'EVT_short_desc' => array('LIKE', $search_string),
1943
-            );
1944
-        }
1945
-        // filter events by venue.
1946
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1947
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1948
-        }
1949
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1950
-        $query_params = apply_filters(
1951
-            'FHEE__Events_Admin_Page__get_events__query_params',
1952
-            array(
1953
-                $where,
1954
-                'limit'    => $limit,
1955
-                'order_by' => $orderby,
1956
-                'order'    => $order,
1957
-                'group_by' => 'EVT_ID',
1958
-            ),
1959
-            $this->_req_data
1960
-        );
1961
-
1962
-        // let's first check if we have special requests coming in.
1963
-        if (isset($this->_req_data['active_status'])) {
1964
-            switch ($this->_req_data['active_status']) {
1965
-                case 'upcoming':
1966
-                    return $EEME->get_upcoming_events($query_params, $count);
1967
-                    break;
1968
-                case 'expired':
1969
-                    return $EEME->get_expired_events($query_params, $count);
1970
-                    break;
1971
-                case 'active':
1972
-                    return $EEME->get_active_events($query_params, $count);
1973
-                    break;
1974
-                case 'inactive':
1975
-                    return $EEME->get_inactive_events($query_params, $count);
1976
-                    break;
1977
-            }
1978
-        }
1979
-
1980
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1981
-        return $events;
1982
-    }
1983
-
1984
-
1985
-    /**
1986
-     * handling for WordPress CPT actions (trash, restore, delete)
1987
-     *
1988
-     * @param string $post_id
1989
-     * @throws EE_Error
1990
-     * @throws InvalidArgumentException
1991
-     * @throws InvalidDataTypeException
1992
-     * @throws InvalidInterfaceException
1993
-     * @throws ReflectionException
1994
-     */
1995
-    public function trash_cpt_item($post_id)
1996
-    {
1997
-        $this->_req_data['EVT_ID'] = $post_id;
1998
-        $this->_trash_or_restore_event('trash', false);
1999
-    }
2000
-
2001
-
2002
-    /**
2003
-     * @param string $post_id
2004
-     * @throws EE_Error
2005
-     * @throws InvalidArgumentException
2006
-     * @throws InvalidDataTypeException
2007
-     * @throws InvalidInterfaceException
2008
-     * @throws ReflectionException
2009
-     */
2010
-    public function restore_cpt_item($post_id)
2011
-    {
2012
-        $this->_req_data['EVT_ID'] = $post_id;
2013
-        $this->_trash_or_restore_event('draft', false);
2014
-    }
2015
-
2016
-
2017
-    /**
2018
-     * @param string $post_id
2019
-     * @throws EE_Error
2020
-     * @throws InvalidArgumentException
2021
-     * @throws InvalidDataTypeException
2022
-     * @throws InvalidInterfaceException
2023
-     * @throws ReflectionException
2024
-     */
2025
-    public function delete_cpt_item($post_id)
2026
-    {
2027
-        $this->_req_data['EVT_ID'] = $post_id;
2028
-        $this->_delete_event(false);
2029
-    }
2030
-
2031
-
2032
-    /**
2033
-     * _trash_or_restore_event
2034
-     *
2035
-     * @access protected
2036
-     * @param string $event_status
2037
-     * @param bool   $redirect_after
2038
-     * @throws EE_Error
2039
-     * @throws InvalidArgumentException
2040
-     * @throws InvalidDataTypeException
2041
-     * @throws InvalidInterfaceException
2042
-     * @throws ReflectionException
2043
-     */
2044
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2045
-    {
2046
-        // determine the event id and set to array.
2047
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2048
-        // loop thru events
2049
-        if ($EVT_ID) {
2050
-            // clean status
2051
-            $event_status = sanitize_key($event_status);
2052
-            // grab status
2053
-            if (! empty($event_status)) {
2054
-                $success = $this->_change_event_status($EVT_ID, $event_status);
2055
-            } else {
2056
-                $success = false;
2057
-                $msg = esc_html__(
2058
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2059
-                    'event_espresso'
2060
-                );
2061
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2062
-            }
2063
-        } else {
2064
-            $success = false;
2065
-            $msg = esc_html__(
2066
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2067
-                'event_espresso'
2068
-            );
2069
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2070
-        }
2071
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2072
-        if ($redirect_after) {
2073
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
2074
-        }
2075
-    }
2076
-
2077
-
2078
-    /**
2079
-     * _trash_or_restore_events
2080
-     *
2081
-     * @access protected
2082
-     * @param string $event_status
2083
-     * @return void
2084
-     * @throws EE_Error
2085
-     * @throws InvalidArgumentException
2086
-     * @throws InvalidDataTypeException
2087
-     * @throws InvalidInterfaceException
2088
-     * @throws ReflectionException
2089
-     */
2090
-    protected function _trash_or_restore_events($event_status = 'trash')
2091
-    {
2092
-        // clean status
2093
-        $event_status = sanitize_key($event_status);
2094
-        // grab status
2095
-        if (! empty($event_status)) {
2096
-            $success = true;
2097
-            // determine the event id and set to array.
2098
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2099
-            // loop thru events
2100
-            foreach ($EVT_IDs as $EVT_ID) {
2101
-                if ($EVT_ID = absint($EVT_ID)) {
2102
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2103
-                    $success = $results !== false ? $success : false;
2104
-                } else {
2105
-                    $msg = sprintf(
2106
-                        esc_html__(
2107
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2108
-                            'event_espresso'
2109
-                        ),
2110
-                        $EVT_ID
2111
-                    );
2112
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2113
-                    $success = false;
2114
-                }
2115
-            }
2116
-        } else {
2117
-            $success = false;
2118
-            $msg = esc_html__(
2119
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2120
-                'event_espresso'
2121
-            );
2122
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2123
-        }
2124
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2125
-        $success = $success ? 2 : false;
2126
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2127
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2128
-    }
2129
-
2130
-
2131
-    /**
2132
-     * _trash_or_restore_events
2133
-     *
2134
-     * @access  private
2135
-     * @param int    $EVT_ID
2136
-     * @param string $event_status
2137
-     * @return bool
2138
-     * @throws EE_Error
2139
-     * @throws InvalidArgumentException
2140
-     * @throws InvalidDataTypeException
2141
-     * @throws InvalidInterfaceException
2142
-     * @throws ReflectionException
2143
-     */
2144
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2145
-    {
2146
-        // grab event id
2147
-        if (! $EVT_ID) {
2148
-            $msg = esc_html__(
2149
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2150
-                'event_espresso'
2151
-            );
2152
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2153
-            return false;
2154
-        }
2155
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2156
-        // clean status
2157
-        $event_status = sanitize_key($event_status);
2158
-        // grab status
2159
-        if (empty($event_status)) {
2160
-            $msg = esc_html__(
2161
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2162
-                'event_espresso'
2163
-            );
2164
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2165
-            return false;
2166
-        }
2167
-        // was event trashed or restored ?
2168
-        switch ($event_status) {
2169
-            case 'draft':
2170
-                $action = 'restored from the trash';
2171
-                $hook = 'AHEE_event_restored_from_trash';
2172
-                break;
2173
-            case 'trash':
2174
-                $action = 'moved to the trash';
2175
-                $hook = 'AHEE_event_moved_to_trash';
2176
-                break;
2177
-            default:
2178
-                $action = 'updated';
2179
-                $hook = false;
2180
-        }
2181
-        // use class to change status
2182
-        $this->_cpt_model_obj->set_status($event_status);
2183
-        $success = $this->_cpt_model_obj->save();
2184
-        if ($success === false) {
2185
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2186
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2187
-            return false;
2188
-        }
2189
-        if ($hook) {
2190
-            do_action($hook);
2191
-        }
2192
-        return true;
2193
-    }
2194
-
2195
-
2196
-    /**
2197
-     * _delete_event
2198
-     *
2199
-     * @access protected
2200
-     * @param bool $redirect_after
2201
-     * @throws EE_Error
2202
-     * @throws InvalidArgumentException
2203
-     * @throws InvalidDataTypeException
2204
-     * @throws InvalidInterfaceException
2205
-     * @throws ReflectionException
2206
-     */
2207
-    protected function _delete_event($redirect_after = true)
2208
-    {
2209
-        // determine the event id and set to array.
2210
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2211
-        $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2212
-        // loop thru events
2213
-        if ($EVT_ID) {
2214
-            $success = $this->_permanently_delete_event($EVT_ID);
2215
-            // get list of events with no prices
2216
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2217
-            // remove this event from the list of events with no prices
2218
-            if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2219
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2220
-            }
2221
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2222
-        } else {
2223
-            $success = false;
2224
-            $msg = esc_html__(
2225
-                'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2226
-                'event_espresso'
2227
-            );
2228
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2229
-        }
2230
-        if ($redirect_after) {
2231
-            $this->_redirect_after_action(
2232
-                $success,
2233
-                'Event',
2234
-                'deleted',
2235
-                array('action' => 'default', 'status' => 'trash')
2236
-            );
2237
-        }
2238
-    }
2239
-
2240
-
2241
-    /**
2242
-     * _delete_events
2243
-     *
2244
-     * @access protected
2245
-     * @return void
2246
-     * @throws EE_Error
2247
-     * @throws InvalidArgumentException
2248
-     * @throws InvalidDataTypeException
2249
-     * @throws InvalidInterfaceException
2250
-     * @throws ReflectionException
2251
-     */
2252
-    protected function _delete_events()
2253
-    {
2254
-        $success = true;
2255
-        // get list of events with no prices
2256
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2257
-        // determine the event id and set to array.
2258
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2259
-        // loop thru events
2260
-        foreach ($EVT_IDs as $EVT_ID) {
2261
-            $EVT_ID = absint($EVT_ID);
2262
-            if ($EVT_ID) {
2263
-                $results = $this->_permanently_delete_event($EVT_ID);
2264
-                $success = $results !== false ? $success : false;
2265
-                // remove this event from the list of events with no prices
2266
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2267
-            } else {
2268
-                $success = false;
2269
-                $msg = esc_html__(
2270
-                    'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2271
-                    'event_espresso'
2272
-                );
2273
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2274
-            }
2275
-        }
2276
-        update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2277
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2278
-        $success = $success ? 2 : false;
2279
-        $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2280
-    }
2281
-
2282
-
2283
-    /**
2284
-     * _permanently_delete_event
2285
-     *
2286
-     * @access  private
2287
-     * @param int $EVT_ID
2288
-     * @return bool
2289
-     * @throws EE_Error
2290
-     * @throws InvalidArgumentException
2291
-     * @throws InvalidDataTypeException
2292
-     * @throws InvalidInterfaceException
2293
-     * @throws ReflectionException
2294
-     */
2295
-    private function _permanently_delete_event($EVT_ID = 0)
2296
-    {
2297
-        // grab event id
2298
-        if (! $EVT_ID) {
2299
-            $msg = esc_html__(
2300
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2301
-                'event_espresso'
2302
-            );
2303
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2304
-            return false;
2305
-        }
2306
-        if (! $this->_cpt_model_obj instanceof EE_Event
2307
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2308
-        ) {
2309
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2310
-        }
2311
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2312
-            return false;
2313
-        }
2314
-        // need to delete related tickets and prices first.
2315
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2316
-        foreach ($datetimes as $datetime) {
2317
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2318
-            $tickets = $datetime->get_many_related('Ticket');
2319
-            foreach ($tickets as $ticket) {
2320
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2321
-                $ticket->delete_related_permanently('Price');
2322
-                $ticket->delete_permanently();
2323
-            }
2324
-            $datetime->delete();
2325
-        }
2326
-        // what about related venues or terms?
2327
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2328
-        foreach ($venues as $venue) {
2329
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2330
-        }
2331
-        // any attached question groups?
2332
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2333
-        if (! empty($question_groups)) {
2334
-            foreach ($question_groups as $question_group) {
2335
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2336
-            }
2337
-        }
2338
-        // Message Template Groups
2339
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2340
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2341
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2342
-        foreach ($term_taxonomies as $term_taxonomy) {
2343
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2344
-        }
2345
-        $success = $this->_cpt_model_obj->delete_permanently();
2346
-        // did it all go as planned ?
2347
-        if ($success) {
2348
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2349
-            EE_Error::add_success($msg);
2350
-        } else {
2351
-            $msg = sprintf(
2352
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2353
-                $EVT_ID
2354
-            );
2355
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2356
-            return false;
2357
-        }
2358
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2359
-        return true;
2360
-    }
2361
-
2362
-
2363
-    /**
2364
-     * get total number of events
2365
-     *
2366
-     * @access public
2367
-     * @return int
2368
-     * @throws EE_Error
2369
-     * @throws InvalidArgumentException
2370
-     * @throws InvalidDataTypeException
2371
-     * @throws InvalidInterfaceException
2372
-     */
2373
-    public function total_events()
2374
-    {
2375
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2376
-        return $count;
2377
-    }
2378
-
2379
-
2380
-    /**
2381
-     * get total number of draft events
2382
-     *
2383
-     * @access public
2384
-     * @return int
2385
-     * @throws EE_Error
2386
-     * @throws InvalidArgumentException
2387
-     * @throws InvalidDataTypeException
2388
-     * @throws InvalidInterfaceException
2389
-     */
2390
-    public function total_events_draft()
2391
-    {
2392
-        $where = array(
2393
-            'status' => array('IN', array('draft', 'auto-draft')),
2394
-        );
2395
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2396
-        return $count;
2397
-    }
2398
-
2399
-
2400
-    /**
2401
-     * get total number of trashed events
2402
-     *
2403
-     * @access public
2404
-     * @return int
2405
-     * @throws EE_Error
2406
-     * @throws InvalidArgumentException
2407
-     * @throws InvalidDataTypeException
2408
-     * @throws InvalidInterfaceException
2409
-     */
2410
-    public function total_trashed_events()
2411
-    {
2412
-        $where = array(
2413
-            'status' => 'trash',
2414
-        );
2415
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2416
-        return $count;
2417
-    }
2418
-
2419
-
2420
-    /**
2421
-     *    _default_event_settings
2422
-     *    This generates the Default Settings Tab
2423
-     *
2424
-     * @return void
2425
-     * @throws DomainException
2426
-     * @throws EE_Error
2427
-     * @throws InvalidArgumentException
2428
-     * @throws InvalidDataTypeException
2429
-     * @throws InvalidInterfaceException
2430
-     */
2431
-    protected function _default_event_settings()
2432
-    {
2433
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2434
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2435
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2436
-        $this->display_admin_page_with_sidebar();
2437
-    }
2438
-
2439
-
2440
-    /**
2441
-     * Return the form for event settings.
2442
-     *
2443
-     * @return EE_Form_Section_Proper
2444
-     * @throws EE_Error
2445
-     */
2446
-    protected function _default_event_settings_form()
2447
-    {
2448
-        $registration_config = EE_Registry::instance()->CFG->registration;
2449
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2450
-            // exclude
2451
-            array(
2452
-                EEM_Registration::status_id_cancelled,
2453
-                EEM_Registration::status_id_declined,
2454
-                EEM_Registration::status_id_incomplete,
2455
-                EEM_Registration::status_id_wait_list,
2456
-            ),
2457
-            true
2458
-        );
2459
-        return new EE_Form_Section_Proper(
2460
-            array(
2461
-                'name'            => 'update_default_event_settings',
2462
-                'html_id'         => 'update_default_event_settings',
2463
-                'html_class'      => 'form-table',
2464
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2465
-                'subsections'     => apply_filters(
2466
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2467
-                    array(
2468
-                        'default_reg_status'  => new EE_Select_Input(
2469
-                            $registration_stati_for_selection,
2470
-                            array(
2471
-                                'default'         => isset($registration_config->default_STS_ID)
2472
-                                                     && array_key_exists(
2473
-                                                         $registration_config->default_STS_ID,
2474
-                                                         $registration_stati_for_selection
2475
-                                                     )
2476
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2477
-                                    : EEM_Registration::status_id_pending_payment,
2478
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2479
-                                                     . EEH_Template::get_help_tab_link(
2480
-                                                         'default_settings_status_help_tab'
2481
-                                                     ),
2482
-                                'html_help_text'  => esc_html__(
2483
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2484
-                                    'event_espresso'
2485
-                                ),
2486
-                            )
2487
-                        ),
2488
-                        'default_max_tickets' => new EE_Integer_Input(
2489
-                            array(
2490
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2491
-                                    ? $registration_config->default_maximum_number_of_tickets
2492
-                                    : EEM_Event::get_default_additional_limit(),
2493
-                                'html_label_text' => esc_html__(
2494
-                                    'Default Maximum Tickets Allowed Per Order:',
2495
-                                    'event_espresso'
2496
-                                )
2497
-                                                     . EEH_Template::get_help_tab_link(
2498
-                                                         'default_maximum_tickets_help_tab"'
2499
-                                                     ),
2500
-                                'html_help_text'  => esc_html__(
2501
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2502
-                                    'event_espresso'
2503
-                                ),
2504
-                            )
2505
-                        ),
2506
-                    )
2507
-                ),
2508
-            )
2509
-        );
2510
-    }
2511
-
2512
-
2513
-    /**
2514
-     * @return void
2515
-     * @throws EE_Error
2516
-     * @throws InvalidArgumentException
2517
-     * @throws InvalidDataTypeException
2518
-     * @throws InvalidInterfaceException
2519
-     */
2520
-    protected function _update_default_event_settings()
2521
-    {
2522
-        $form = $this->_default_event_settings_form();
2523
-        if ($form->was_submitted()) {
2524
-            $form->receive_form_submission();
2525
-            if ($form->is_valid()) {
2526
-                $registration_config = EE_Registry::instance()->CFG->registration;
2527
-                $valid_data = $form->valid_data();
2528
-                if (isset($valid_data['default_reg_status'])) {
2529
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2530
-                }
2531
-                if (isset($valid_data['default_max_tickets'])) {
2532
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2533
-                }
2534
-                do_action(
2535
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2536
-                    $valid_data,
2537
-                    EE_Registry::instance()->CFG,
2538
-                    $this
2539
-                );
2540
-                // update because data was valid!
2541
-                EE_Registry::instance()->CFG->update_espresso_config();
2542
-                EE_Error::overwrite_success();
2543
-                EE_Error::add_success(
2544
-                    __('Default Event Settings were updated', 'event_espresso')
2545
-                );
2546
-            }
2547
-        }
2548
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2549
-    }
2550
-
2551
-
2552
-    /*************        Templates        *************/
2553
-    protected function _template_settings()
2554
-    {
2555
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2556
-        $this->_template_args['preview_img'] = '<img src="'
2557
-                                               . EVENTS_ASSETS_URL
2558
-                                               . '/images/'
2559
-                                               . 'caffeinated_template_features.jpg" alt="'
2560
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2561
-                                               . '" />';
2562
-        $this->_template_args['preview_text'] = '<strong>'
2563
-                                                . esc_html__(
2564
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2565
-                                                    'event_espresso'
2566
-                                                ) . '</strong>';
2567
-        $this->display_admin_caf_preview_page('template_settings_tab');
2568
-    }
2569
-
2570
-
2571
-    /** Event Category Stuff **/
2572
-    /**
2573
-     * set the _category property with the category object for the loaded page.
2574
-     *
2575
-     * @access private
2576
-     * @return void
2577
-     */
2578
-    private function _set_category_object()
2579
-    {
2580
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2581
-            return;
2582
-        } //already have the category object so get out.
2583
-        // set default category object
2584
-        $this->_set_empty_category_object();
2585
-        // only set if we've got an id
2586
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2587
-            return;
2588
-        }
2589
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2590
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2591
-        if (! empty($term)) {
2592
-            $this->_category->category_name = $term->name;
2593
-            $this->_category->category_identifier = $term->slug;
2594
-            $this->_category->category_desc = $term->description;
2595
-            $this->_category->id = $term->term_id;
2596
-            $this->_category->parent = $term->parent;
2597
-        }
2598
-    }
2599
-
2600
-
2601
-    /**
2602
-     * Clears out category properties.
2603
-     */
2604
-    private function _set_empty_category_object()
2605
-    {
2606
-        $this->_category = new stdClass();
2607
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2608
-        $this->_category->id = $this->_category->parent = 0;
2609
-    }
2610
-
2611
-
2612
-    /**
2613
-     * @throws DomainException
2614
-     * @throws EE_Error
2615
-     * @throws InvalidArgumentException
2616
-     * @throws InvalidDataTypeException
2617
-     * @throws InvalidInterfaceException
2618
-     */
2619
-    protected function _category_list_table()
2620
-    {
2621
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2622
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2623
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2624
-            'add_category',
2625
-            'add_category',
2626
-            array(),
2627
-            'add-new-h2'
2628
-        );
2629
-        $this->display_admin_list_table_page_with_sidebar();
2630
-    }
2631
-
2632
-
2633
-    /**
2634
-     * Output category details view.
2635
-     *
2636
-     * @param string $view
2637
-     * @throws DomainException
2638
-     * @throws EE_Error
2639
-     * @throws InvalidArgumentException
2640
-     * @throws InvalidDataTypeException
2641
-     * @throws InvalidInterfaceException
2642
-     */
2643
-    protected function _category_details($view)
2644
-    {
2645
-        // load formatter helper
2646
-        // load field generator helper
2647
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2648
-        $this->_set_add_edit_form_tags($route);
2649
-        $this->_set_category_object();
2650
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2651
-        $delete_action = 'delete_category';
2652
-        // custom redirect
2653
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2654
-            array('action' => 'category_list'),
2655
-            $this->_admin_base_url
2656
-        );
2657
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2658
-        // take care of contents
2659
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2660
-        $this->display_admin_page_with_sidebar();
2661
-    }
2662
-
2663
-
2664
-    /**
2665
-     * Output category details content.
2666
-     *
2667
-     * @throws DomainException
2668
-     */
2669
-    protected function _category_details_content()
2670
-    {
2671
-        $editor_args['category_desc'] = array(
2672
-            'type'          => 'wp_editor',
2673
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2674
-            'class'         => 'my_editor_custom',
2675
-            'wpeditor_args' => array('media_buttons' => false),
2676
-        );
2677
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2678
-        $all_terms = get_terms(
2679
-            array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2680
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2681
-        );
2682
-        // setup category select for term parents.
2683
-        $category_select_values[] = array(
2684
-            'text' => esc_html__('No Parent', 'event_espresso'),
2685
-            'id'   => 0,
2686
-        );
2687
-        foreach ($all_terms as $term) {
2688
-            $category_select_values[] = array(
2689
-                'text' => $term->name,
2690
-                'id'   => $term->term_id,
2691
-            );
2692
-        }
2693
-        $category_select = EEH_Form_Fields::select_input(
2694
-            'category_parent',
2695
-            $category_select_values,
2696
-            $this->_category->parent
2697
-        );
2698
-        $template_args = array(
2699
-            'category'                 => $this->_category,
2700
-            'category_select'          => $category_select,
2701
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2702
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2703
-            'disable'                  => '',
2704
-            'disabled_message'         => false,
2705
-        );
2706
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2707
-        return EEH_Template::display_template($template, $template_args, true);
2708
-    }
2709
-
2710
-
2711
-    /**
2712
-     * Handles deleting categories.
2713
-     */
2714
-    protected function _delete_categories()
2715
-    {
2716
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2717
-            : (array) $this->_req_data['category_id'];
2718
-        foreach ($cat_ids as $cat_id) {
2719
-            $this->_delete_category($cat_id);
2720
-        }
2721
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2722
-        $query_args = array(
2723
-            'action' => 'category_list',
2724
-        );
2725
-        $this->_redirect_after_action(0, '', '', $query_args);
2726
-    }
2727
-
2728
-
2729
-    /**
2730
-     * Handles deleting specific category.
2731
-     *
2732
-     * @param int $cat_id
2733
-     */
2734
-    protected function _delete_category($cat_id)
2735
-    {
2736
-        $cat_id = absint($cat_id);
2737
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2738
-    }
2739
-
2740
-
2741
-    /**
2742
-     * Handles triggering the update or insertion of a new category.
2743
-     *
2744
-     * @param bool $new_category true means we're triggering the insert of a new category.
2745
-     * @throws EE_Error
2746
-     * @throws InvalidArgumentException
2747
-     * @throws InvalidDataTypeException
2748
-     * @throws InvalidInterfaceException
2749
-     */
2750
-    protected function _insert_or_update_category($new_category)
2751
-    {
2752
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2753
-        $success = 0; // we already have a success message so lets not send another.
2754
-        if ($cat_id) {
2755
-            $query_args = array(
2756
-                'action'     => 'edit_category',
2757
-                'EVT_CAT_ID' => $cat_id,
2758
-            );
2759
-        } else {
2760
-            $query_args = array('action' => 'add_category');
2761
-        }
2762
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2763
-    }
2764
-
2765
-
2766
-    /**
2767
-     * Inserts or updates category
2768
-     *
2769
-     * @param bool $update (true indicates we're updating a category).
2770
-     * @return bool|mixed|string
2771
-     */
2772
-    private function _insert_category($update = false)
2773
-    {
2774
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2775
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2776
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2777
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2778
-        if (empty($category_name)) {
2779
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2780
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2781
-            return false;
2782
-        }
2783
-        $term_args = array(
2784
-            'name'        => $category_name,
2785
-            'description' => $category_desc,
2786
-            'parent'      => $category_parent,
2787
-        );
2788
-        // was the category_identifier input disabled?
2789
-        if (isset($this->_req_data['category_identifier'])) {
2790
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2791
-        }
2792
-        $insert_ids = $update
2793
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2794
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2795
-        if (! is_array($insert_ids)) {
2796
-            $msg = esc_html__(
2797
-                'An error occurred and the category has not been saved to the database.',
2798
-                'event_espresso'
2799
-            );
2800
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2801
-        } else {
2802
-            $cat_id = $insert_ids['term_id'];
2803
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2804
-            EE_Error::add_success($msg);
2805
-        }
2806
-        return $cat_id;
2807
-    }
2808
-
2809
-
2810
-    /**
2811
-     * Gets categories or count of categories matching the arguments in the request.
2812
-     *
2813
-     * @param int  $per_page
2814
-     * @param int  $current_page
2815
-     * @param bool $count
2816
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2817
-     * @throws EE_Error
2818
-     * @throws InvalidArgumentException
2819
-     * @throws InvalidDataTypeException
2820
-     * @throws InvalidInterfaceException
2821
-     */
2822
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2823
-    {
2824
-        // testing term stuff
2825
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2826
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2827
-        $limit = ($current_page - 1) * $per_page;
2828
-        $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2829
-        if (isset($this->_req_data['s'])) {
2830
-            $sstr = '%' . $this->_req_data['s'] . '%';
2831
-            $where['OR'] = array(
2832
-                'Term.name'   => array('LIKE', $sstr),
2833
-                'description' => array('LIKE', $sstr),
2834
-            );
2835
-        }
2836
-        $query_params = array(
2837
-            $where,
2838
-            'order_by'   => array($orderby => $order),
2839
-            'limit'      => $limit . ',' . $per_page,
2840
-            'force_join' => array('Term'),
2841
-        );
2842
-        $categories = $count
2843
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2844
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2845
-        return $categories;
2846
-    }
2847
-
2848
-    /* end category stuff */
2849
-    /**************/
2850
-
2851
-
2852
-    /**
2853
-     * Callback for the `ee_save_timezone_setting` ajax action.
2854
-     *
2855
-     * @throws EE_Error
2856
-     * @throws InvalidArgumentException
2857
-     * @throws InvalidDataTypeException
2858
-     * @throws InvalidInterfaceException
2859
-     */
2860
-    public function save_timezonestring_setting()
2861
-    {
2862
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2863
-            ? $this->_req_data['timezone_selected']
2864
-            : '';
2865
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2866
-            EE_Error::add_error(
2867
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2868
-                __FILE__,
2869
-                __FUNCTION__,
2870
-                __LINE__
2871
-            );
2872
-            $this->_template_args['error'] = true;
2873
-            $this->_return_json();
2874
-        }
2875
-
2876
-        update_option('timezone_string', $timezone_string);
2877
-        EE_Error::add_success(
2878
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2879
-        );
2880
-        $this->_template_args['success'] = true;
2881
-        $this->_return_json(true, array('action' => 'create_new'));
2882
-    }
18
+	/**
19
+	 * This will hold the event object for event_details screen.
20
+	 *
21
+	 * @access protected
22
+	 * @var EE_Event $_event
23
+	 */
24
+	protected $_event;
25
+
26
+
27
+	/**
28
+	 * This will hold the category object for category_details screen.
29
+	 *
30
+	 * @var stdClass $_category
31
+	 */
32
+	protected $_category;
33
+
34
+
35
+	/**
36
+	 * This will hold the event model instance
37
+	 *
38
+	 * @var EEM_Event $_event_model
39
+	 */
40
+	protected $_event_model;
41
+
42
+
43
+	/**
44
+	 * @var EE_Event
45
+	 */
46
+	protected $_cpt_model_obj = false;
47
+
48
+
49
+	/**
50
+	 * Initialize page props for this admin page group.
51
+	 */
52
+	protected function _init_page_props()
53
+	{
54
+		$this->page_slug = EVENTS_PG_SLUG;
55
+		$this->page_label = EVENTS_LABEL;
56
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
57
+		$this->_admin_base_path = EVENTS_ADMIN;
58
+		$this->_cpt_model_names = array(
59
+			'create_new' => 'EEM_Event',
60
+			'edit'       => 'EEM_Event',
61
+		);
62
+		$this->_cpt_edit_routes = array(
63
+			'espresso_events' => 'edit',
64
+		);
65
+		add_action(
66
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
67
+			array($this, 'verify_event_edit'),
68
+			10,
69
+			2
70
+		);
71
+	}
72
+
73
+
74
+	/**
75
+	 * Sets the ajax hooks used for this admin page group.
76
+	 */
77
+	protected function _ajax_hooks()
78
+	{
79
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
80
+	}
81
+
82
+
83
+	/**
84
+	 * Sets the page properties for this admin page group.
85
+	 */
86
+	protected function _define_page_props()
87
+	{
88
+		$this->_admin_page_title = EVENTS_LABEL;
89
+		$this->_labels = array(
90
+			'buttons'      => array(
91
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
92
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
93
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
94
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
95
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
96
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
97
+			),
98
+			'editor_title' => array(
99
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
100
+			),
101
+			'publishbox'   => array(
102
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
103
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
104
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
105
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
106
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
107
+			),
108
+		);
109
+	}
110
+
111
+
112
+	/**
113
+	 * Sets the page routes property for this admin page group.
114
+	 */
115
+	protected function _set_page_routes()
116
+	{
117
+		// load formatter helper
118
+		// load field generator helper
119
+		// is there a evt_id in the request?
120
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
121
+			? $this->_req_data['EVT_ID']
122
+			: 0;
123
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
124
+		$this->_page_routes = array(
125
+			'default'                       => array(
126
+				'func'       => '_events_overview_list_table',
127
+				'capability' => 'ee_read_events',
128
+			),
129
+			'create_new'                    => array(
130
+				'func'       => '_create_new_cpt_item',
131
+				'capability' => 'ee_edit_events',
132
+			),
133
+			'edit'                          => array(
134
+				'func'       => '_edit_cpt_item',
135
+				'capability' => 'ee_edit_event',
136
+				'obj_id'     => $evt_id,
137
+			),
138
+			'copy_event'                    => array(
139
+				'func'       => '_copy_events',
140
+				'capability' => 'ee_edit_event',
141
+				'obj_id'     => $evt_id,
142
+				'noheader'   => true,
143
+			),
144
+			'trash_event'                   => array(
145
+				'func'       => '_trash_or_restore_event',
146
+				'args'       => array('event_status' => 'trash'),
147
+				'capability' => 'ee_delete_event',
148
+				'obj_id'     => $evt_id,
149
+				'noheader'   => true,
150
+			),
151
+			'trash_events'                  => array(
152
+				'func'       => '_trash_or_restore_events',
153
+				'args'       => array('event_status' => 'trash'),
154
+				'capability' => 'ee_delete_events',
155
+				'noheader'   => true,
156
+			),
157
+			'restore_event'                 => array(
158
+				'func'       => '_trash_or_restore_event',
159
+				'args'       => array('event_status' => 'draft'),
160
+				'capability' => 'ee_delete_event',
161
+				'obj_id'     => $evt_id,
162
+				'noheader'   => true,
163
+			),
164
+			'restore_events'                => array(
165
+				'func'       => '_trash_or_restore_events',
166
+				'args'       => array('event_status' => 'draft'),
167
+				'capability' => 'ee_delete_events',
168
+				'noheader'   => true,
169
+			),
170
+			'delete_event'                  => array(
171
+				'func'       => '_delete_event',
172
+				'capability' => 'ee_delete_event',
173
+				'obj_id'     => $evt_id,
174
+				'noheader'   => true,
175
+			),
176
+			'delete_events'                 => array(
177
+				'func'       => '_delete_events',
178
+				'capability' => 'ee_delete_events',
179
+				'noheader'   => true,
180
+			),
181
+			'view_report'                   => array(
182
+				'func'      => '_view_report',
183
+				'capability' => 'ee_edit_events',
184
+			),
185
+			'default_event_settings'        => array(
186
+				'func'       => '_default_event_settings',
187
+				'capability' => 'manage_options',
188
+			),
189
+			'update_default_event_settings' => array(
190
+				'func'       => '_update_default_event_settings',
191
+				'capability' => 'manage_options',
192
+				'noheader'   => true,
193
+			),
194
+			'template_settings'             => array(
195
+				'func'       => '_template_settings',
196
+				'capability' => 'manage_options',
197
+			),
198
+			// event category tab related
199
+			'add_category'                  => array(
200
+				'func'       => '_category_details',
201
+				'capability' => 'ee_edit_event_category',
202
+				'args'       => array('add'),
203
+			),
204
+			'edit_category'                 => array(
205
+				'func'       => '_category_details',
206
+				'capability' => 'ee_edit_event_category',
207
+				'args'       => array('edit'),
208
+			),
209
+			'delete_categories'             => array(
210
+				'func'       => '_delete_categories',
211
+				'capability' => 'ee_delete_event_category',
212
+				'noheader'   => true,
213
+			),
214
+			'delete_category'               => array(
215
+				'func'       => '_delete_categories',
216
+				'capability' => 'ee_delete_event_category',
217
+				'noheader'   => true,
218
+			),
219
+			'insert_category'               => array(
220
+				'func'       => '_insert_or_update_category',
221
+				'args'       => array('new_category' => true),
222
+				'capability' => 'ee_edit_event_category',
223
+				'noheader'   => true,
224
+			),
225
+			'update_category'               => array(
226
+				'func'       => '_insert_or_update_category',
227
+				'args'       => array('new_category' => false),
228
+				'capability' => 'ee_edit_event_category',
229
+				'noheader'   => true,
230
+			),
231
+			'category_list'                 => array(
232
+				'func'       => '_category_list_table',
233
+				'capability' => 'ee_manage_event_categories',
234
+			),
235
+		);
236
+	}
237
+
238
+
239
+	/**
240
+	 * Set the _page_config property for this admin page group.
241
+	 */
242
+	protected function _set_page_config()
243
+	{
244
+		$this->_page_config = [
245
+			'default'                => [
246
+				'nav'           => [
247
+					'label' => esc_html__('Overview', 'event_espresso'),
248
+					'order' => 10,
249
+				],
250
+				'list_table'    => 'Events_Admin_List_Table',
251
+				'help_tabs'     => [
252
+					'events_overview_help_tab'                       => [
253
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
254
+						'filename' => 'events_overview',
255
+					],
256
+					'events_overview_table_column_headings_help_tab' => [
257
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
258
+						'filename' => 'events_overview_table_column_headings',
259
+					],
260
+					'events_overview_filters_help_tab'               => [
261
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
262
+						'filename' => 'events_overview_filters',
263
+					],
264
+					'events_overview_view_help_tab'                  => [
265
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
266
+						'filename' => 'events_overview_views',
267
+					],
268
+					'events_overview_other_help_tab'                 => [
269
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
270
+						'filename' => 'events_overview_other',
271
+					],
272
+				],
273
+				'help_tour'     => [
274
+					'Event_Overview_Help_Tour',
275
+					// 'New_Features_Test_Help_Tour' for testing multiple help tour
276
+				],
277
+				'require_nonce' => false,
278
+				'qtips' => ['EE_Event_List_Table_Tips'],
279
+			],
280
+			'create_new'             => [
281
+				'nav'           => [
282
+					'label'      => esc_html__('Add Event', 'event_espresso'),
283
+					'order'      => 5,
284
+					'persistent' => false,
285
+				],
286
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
287
+				'help_tabs'     => [
288
+					'event_editor_help_tab'                            => [
289
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
290
+						'filename' => 'event_editor',
291
+					],
292
+					'event_editor_title_richtexteditor_help_tab'       => [
293
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
294
+						'filename' => 'event_editor_title_richtexteditor',
295
+					],
296
+					'event_editor_venue_details_help_tab'              => [
297
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
298
+						'filename' => 'event_editor_venue_details',
299
+					],
300
+					'event_editor_event_datetimes_help_tab'            => [
301
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
302
+						'filename' => 'event_editor_event_datetimes',
303
+					],
304
+					'event_editor_event_tickets_help_tab'              => [
305
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
306
+						'filename' => 'event_editor_event_tickets',
307
+					],
308
+					'event_editor_event_registration_options_help_tab' => [
309
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
310
+						'filename' => 'event_editor_event_registration_options',
311
+					],
312
+					'event_editor_tags_categories_help_tab'            => [
313
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
314
+						'filename' => 'event_editor_tags_categories',
315
+					],
316
+					'event_editor_questions_registrants_help_tab'      => [
317
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
318
+						'filename' => 'event_editor_questions_registrants',
319
+					],
320
+					'event_editor_save_new_event_help_tab'             => [
321
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
322
+						'filename' => 'event_editor_save_new_event',
323
+					],
324
+					'event_editor_other_help_tab'                      => [
325
+						'title'    => esc_html__('Event Other', 'event_espresso'),
326
+						'filename' => 'event_editor_other',
327
+					],
328
+				],
329
+				'help_tour'     => [
330
+					'Event_Editor_Help_Tour',
331
+				],
332
+				'require_nonce' => false,
333
+			],
334
+			'edit'                   => [
335
+				'nav'           => [
336
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
337
+					'order'      => 5,
338
+					'persistent' => false,
339
+					'url'        => isset($this->_req_data['post'])
340
+						? EE_Admin_Page::add_query_args_and_nonce(
341
+							['post' => $this->_req_data['post'], 'action' => 'edit'],
342
+							$this->_current_page_view_url
343
+						)
344
+						: $this->_admin_base_url,
345
+				],
346
+				'metaboxes'     => ['_register_event_editor_meta_boxes'],
347
+				'help_tabs'     => [
348
+					'event_editor_help_tab'                            => [
349
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
350
+						'filename' => 'event_editor',
351
+					],
352
+					'event_editor_title_richtexteditor_help_tab'       => [
353
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
354
+						'filename' => 'event_editor_title_richtexteditor',
355
+					],
356
+					'event_editor_venue_details_help_tab'              => [
357
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
358
+						'filename' => 'event_editor_venue_details',
359
+					],
360
+					'event_editor_event_datetimes_help_tab'            => [
361
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
362
+						'filename' => 'event_editor_event_datetimes',
363
+					],
364
+					'event_editor_event_tickets_help_tab'              => [
365
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
366
+						'filename' => 'event_editor_event_tickets',
367
+					],
368
+					'event_editor_event_registration_options_help_tab' => [
369
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
370
+						'filename' => 'event_editor_event_registration_options',
371
+					],
372
+					'event_editor_tags_categories_help_tab'            => [
373
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
374
+						'filename' => 'event_editor_tags_categories',
375
+					],
376
+					'event_editor_questions_registrants_help_tab'      => [
377
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
378
+						'filename' => 'event_editor_questions_registrants',
379
+					],
380
+					'event_editor_save_new_event_help_tab'             => [
381
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
382
+						'filename' => 'event_editor_save_new_event',
383
+					],
384
+					'event_editor_other_help_tab'                      => [
385
+						'title'    => esc_html__('Event Other', 'event_espresso'),
386
+						'filename' => 'event_editor_other',
387
+					],
388
+				],
389
+				'require_nonce' => false,
390
+			],
391
+			'default_event_settings' => [
392
+				'nav'           => [
393
+					'label' => esc_html__('Default Settings', 'event_espresso'),
394
+					'order' => 40,
395
+				],
396
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
397
+				'labels'        => [
398
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
399
+				],
400
+				'help_tabs'     => [
401
+					'default_settings_help_tab'        => [
402
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
403
+						'filename' => 'events_default_settings',
404
+					],
405
+					'default_settings_status_help_tab' => [
406
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
407
+						'filename' => 'events_default_settings_status',
408
+					],
409
+					'default_maximum_tickets_help_tab' => [
410
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
411
+						'filename' => 'events_default_settings_max_tickets',
412
+					],
413
+				],
414
+				'help_tour'     => ['Event_Default_Settings_Help_Tour'],
415
+				'require_nonce' => false,
416
+			],
417
+			// template settings
418
+			'template_settings'      => [
419
+				'nav'           => [
420
+					'label' => esc_html__('Templates', 'event_espresso'),
421
+					'order' => 30,
422
+				],
423
+				'metaboxes'     => $this->_default_espresso_metaboxes,
424
+				'help_tabs'     => [
425
+					'general_settings_templates_help_tab' => [
426
+						'title'    => esc_html__('Templates', 'event_espresso'),
427
+						'filename' => 'general_settings_templates',
428
+					],
429
+				],
430
+				'help_tour'     => ['Templates_Help_Tour'],
431
+				'require_nonce' => false,
432
+			],
433
+			// event category stuff
434
+			'add_category'           => [
435
+				'nav'           => [
436
+					'label'      => esc_html__('Add Category', 'event_espresso'),
437
+					'order'      => 15,
438
+					'persistent' => false,
439
+				],
440
+				'help_tabs'     => [
441
+					'add_category_help_tab' => [
442
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
443
+						'filename' => 'events_add_category',
444
+					],
445
+				],
446
+				'help_tour'     => ['Event_Add_Category_Help_Tour'],
447
+				'metaboxes'     => ['_publish_post_box'],
448
+				'require_nonce' => false,
449
+			],
450
+			'edit_category'          => [
451
+				'nav'           => [
452
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
453
+					'order'      => 15,
454
+					'persistent' => false,
455
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
456
+						? add_query_arg(
457
+							['EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']],
458
+							$this->_current_page_view_url
459
+						)
460
+						: $this->_admin_base_url,
461
+				],
462
+				'help_tabs'     => [
463
+					'edit_category_help_tab' => [
464
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
465
+						'filename' => 'events_edit_category',
466
+					],
467
+				],
468
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
469
+				'metaboxes'     => ['_publish_post_box'],
470
+				'require_nonce' => false,
471
+			],
472
+			'category_list'          => [
473
+				'nav'           => [
474
+					'label' => esc_html__('Categories', 'event_espresso'),
475
+					'order' => 20,
476
+				],
477
+				'list_table'    => 'Event_Categories_Admin_List_Table',
478
+				'help_tabs'     => [
479
+					'events_categories_help_tab'                       => [
480
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
481
+						'filename' => 'events_categories',
482
+					],
483
+					'events_categories_table_column_headings_help_tab' => [
484
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
485
+						'filename' => 'events_categories_table_column_headings',
486
+					],
487
+					'events_categories_view_help_tab'                  => [
488
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
489
+						'filename' => 'events_categories_views',
490
+					],
491
+					'events_categories_other_help_tab'                 => [
492
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
493
+						'filename' => 'events_categories_other',
494
+					],
495
+				],
496
+				'help_tour'     => [
497
+					'Event_Categories_Help_Tour',
498
+				],
499
+				'metaboxes'     => $this->_default_espresso_metaboxes,
500
+				'require_nonce' => false,
501
+			],
502
+		];
503
+		// only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
504
+		$domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
505
+		if (! $domain->isCaffeinated()) {
506
+			$this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
507
+			$this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips' ];
508
+		}
509
+	}
510
+
511
+
512
+	/**
513
+	 * Used to register any global screen options if necessary for every route in this admin page group.
514
+	 */
515
+	protected function _add_screen_options()
516
+	{
517
+	}
518
+
519
+
520
+	/**
521
+	 * Implementing the screen options for the 'default' route.
522
+	 *
523
+	 * @throws InvalidArgumentException
524
+	 * @throws InvalidDataTypeException
525
+	 * @throws InvalidInterfaceException
526
+	 */
527
+	protected function _add_screen_options_default()
528
+	{
529
+		$this->_per_page_screen_option();
530
+	}
531
+
532
+
533
+	/**
534
+	 * Implementing screen options for the category list route.
535
+	 *
536
+	 * @throws InvalidArgumentException
537
+	 * @throws InvalidDataTypeException
538
+	 * @throws InvalidInterfaceException
539
+	 */
540
+	protected function _add_screen_options_category_list()
541
+	{
542
+		$page_title = $this->_admin_page_title;
543
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
544
+		$this->_per_page_screen_option();
545
+		$this->_admin_page_title = $page_title;
546
+	}
547
+
548
+
549
+	/**
550
+	 * Used to register any global feature pointers for the admin page group.
551
+	 */
552
+	protected function _add_feature_pointers()
553
+	{
554
+	}
555
+
556
+
557
+	/**
558
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
559
+	 */
560
+	public function load_scripts_styles()
561
+	{
562
+		wp_register_style(
563
+			'events-admin-css',
564
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
565
+			[],
566
+			EVENT_ESPRESSO_VERSION
567
+		);
568
+		wp_register_style(
569
+			'ee-cat-admin',
570
+			EVENTS_ASSETS_URL . 'ee-cat-admin.css',
571
+			[],
572
+			EVENT_ESPRESSO_VERSION
573
+		);
574
+		wp_enqueue_style('events-admin-css');
575
+		wp_enqueue_style('ee-cat-admin');
576
+		// scripts
577
+		wp_register_script(
578
+			'event_editor_js',
579
+			EVENTS_ASSETS_URL . 'event_editor.js',
580
+			['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
581
+			EVENT_ESPRESSO_VERSION,
582
+			true
583
+		);
584
+	}
585
+
586
+
587
+	/**
588
+	 * Enqueuing scripts and styles specific to this view
589
+	 */
590
+	public function load_scripts_styles_create_new()
591
+	{
592
+		$this->load_scripts_styles_edit();
593
+	}
594
+
595
+
596
+	/**
597
+	 * Enqueuing scripts and styles specific to this view
598
+	 */
599
+	public function load_scripts_styles_edit()
600
+	{
601
+		// styles
602
+		wp_enqueue_style('espresso-ui-theme');
603
+		wp_register_style(
604
+			'event-editor-css',
605
+			EVENTS_ASSETS_URL . 'event-editor.css',
606
+			['ee-admin-css'],
607
+			EVENT_ESPRESSO_VERSION
608
+		);
609
+		wp_enqueue_style('event-editor-css');
610
+		// scripts
611
+		if (! $this->admin_config->useAdvancedEditor()) {
612
+			wp_register_script(
613
+				'event-datetime-metabox',
614
+				EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
615
+				['event_editor_js', 'ee-datepicker'],
616
+				EVENT_ESPRESSO_VERSION
617
+			);
618
+			wp_enqueue_script('event-datetime-metabox');
619
+		}
620
+	}
621
+
622
+
623
+	/**
624
+	 * Populating the _views property for the category list table view.
625
+	 */
626
+	protected function _set_list_table_views_category_list()
627
+	{
628
+		$this->_views = array(
629
+			'all' => array(
630
+				'slug'        => 'all',
631
+				'label'       => esc_html__('All', 'event_espresso'),
632
+				'count'       => 0,
633
+				'bulk_action' => array(
634
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
635
+				),
636
+			),
637
+		);
638
+	}
639
+
640
+
641
+	/**
642
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
643
+	 */
644
+	public function admin_init()
645
+	{
646
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
647
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
648
+			'event_espresso'
649
+		);
650
+	}
651
+
652
+
653
+	/**
654
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
655
+	 * group.
656
+	 */
657
+	public function admin_notices()
658
+	{
659
+	}
660
+
661
+
662
+	/**
663
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
664
+	 * this admin page group.
665
+	 */
666
+	public function admin_footer_scripts()
667
+	{
668
+	}
669
+
670
+
671
+	/**
672
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
673
+	 * warning (via EE_Error::add_error());
674
+	 *
675
+	 * @param  EE_Event $event Event object
676
+	 * @param string    $req_type
677
+	 * @return void
678
+	 * @throws EE_Error
679
+	 * @access public
680
+	 */
681
+	public function verify_event_edit($event = null, $req_type = '')
682
+	{
683
+		// don't need to do this when processing
684
+		if (! empty($req_type)) {
685
+			return;
686
+		}
687
+		// no event?
688
+		if (! $event instanceof EE_Event) {
689
+			$event = $this->_cpt_model_obj;
690
+		}
691
+		// STILL no event?
692
+		if (! $event instanceof EE_Event) {
693
+			return;
694
+		}
695
+		$orig_status = $event->status();
696
+		// first check if event is active.
697
+		if ($orig_status === EEM_Event::cancelled
698
+			|| $orig_status === EEM_Event::postponed
699
+			|| $event->is_expired()
700
+			|| $event->is_inactive()
701
+		) {
702
+			return;
703
+		}
704
+		// made it here so it IS active... next check that any of the tickets are sold.
705
+		if ($event->is_sold_out(true)) {
706
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
707
+				EE_Error::add_attention(
708
+					sprintf(
709
+						esc_html__(
710
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
711
+							'event_espresso'
712
+						),
713
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
714
+					)
715
+				);
716
+			}
717
+			return;
718
+		}
719
+		if ($orig_status === EEM_Event::sold_out) {
720
+			EE_Error::add_attention(
721
+				sprintf(
722
+					esc_html__(
723
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
724
+						'event_espresso'
725
+					),
726
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
727
+				)
728
+			);
729
+		}
730
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
731
+		if (! $event->tickets_on_sale()) {
732
+			return;
733
+		}
734
+		// made it here so show warning
735
+		$this->_edit_event_warning();
736
+	}
737
+
738
+
739
+	/**
740
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
741
+	 * When needed, hook this into a EE_Error::add_error() notice.
742
+	 *
743
+	 * @access protected
744
+	 * @return void
745
+	 */
746
+	protected function _edit_event_warning()
747
+	{
748
+		// we don't want to add warnings during these requests
749
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
750
+			return;
751
+		}
752
+		EE_Error::add_attention(
753
+			sprintf(
754
+				esc_html__(
755
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
756
+					'event_espresso'
757
+				),
758
+				'<a class="espresso-help-tab-lnk">',
759
+				'</a>'
760
+			)
761
+		);
762
+	}
763
+
764
+
765
+	/**
766
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
767
+	 * Otherwise, do the normal logic
768
+	 *
769
+	 * @return string
770
+	 * @throws EE_Error
771
+	 * @throws InvalidArgumentException
772
+	 * @throws InvalidDataTypeException
773
+	 * @throws InvalidInterfaceException
774
+	 */
775
+	protected function _create_new_cpt_item()
776
+	{
777
+		$has_timezone_string = get_option('timezone_string');
778
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
779
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
780
+			EE_Error::add_attention(
781
+				sprintf(
782
+					__(
783
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
784
+						'event_espresso'
785
+					),
786
+					'<br>',
787
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
788
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
789
+					. '</select>',
790
+					'<button class="button button-secondary timezone-submit">',
791
+					'</button><span class="spinner"></span>'
792
+				),
793
+				__FILE__,
794
+				__FUNCTION__,
795
+				__LINE__
796
+			);
797
+		}
798
+		parent::_create_new_cpt_item();
799
+	}
800
+
801
+
802
+	/**
803
+	 * Sets the _views property for the default route in this admin page group.
804
+	 */
805
+	protected function _set_list_table_views_default()
806
+	{
807
+		$this->_views = array(
808
+			'all'   => array(
809
+				'slug'        => 'all',
810
+				'label'       => esc_html__('View All Events', 'event_espresso'),
811
+				'count'       => 0,
812
+				'bulk_action' => array(
813
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
814
+				),
815
+			),
816
+			'draft' => array(
817
+				'slug'        => 'draft',
818
+				'label'       => esc_html__('Draft', 'event_espresso'),
819
+				'count'       => 0,
820
+				'bulk_action' => array(
821
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
822
+				),
823
+			),
824
+		);
825
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
826
+			$this->_views['trash'] = array(
827
+				'slug'        => 'trash',
828
+				'label'       => esc_html__('Trash', 'event_espresso'),
829
+				'count'       => 0,
830
+				'bulk_action' => array(
831
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
832
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
833
+				),
834
+			);
835
+		}
836
+	}
837
+
838
+
839
+	/**
840
+	 * Provides the legend item array for the default list table view.
841
+	 *
842
+	 * @return array
843
+	 */
844
+	protected function _event_legend_items()
845
+	{
846
+		$items = array(
847
+			'view_details'   => array(
848
+				'class' => 'dashicons dashicons-search',
849
+				'desc'  => esc_html__('View Event', 'event_espresso'),
850
+			),
851
+			'edit_event'     => array(
852
+				'class' => 'ee-icon ee-icon-calendar-edit',
853
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
854
+			),
855
+			'view_attendees' => array(
856
+				'class' => 'dashicons dashicons-groups',
857
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
858
+			),
859
+		);
860
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
861
+		$statuses = array(
862
+			'sold_out_status'  => array(
863
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
864
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
865
+			),
866
+			'active_status'    => array(
867
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
868
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
869
+			),
870
+			'upcoming_status'  => array(
871
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
872
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
873
+			),
874
+			'postponed_status' => array(
875
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
876
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
877
+			),
878
+			'cancelled_status' => array(
879
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
880
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
881
+			),
882
+			'expired_status'   => array(
883
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
884
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
885
+			),
886
+			'inactive_status'  => array(
887
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
888
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
889
+			),
890
+		);
891
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
892
+		return array_merge($items, $statuses);
893
+	}
894
+
895
+
896
+	/**
897
+	 * @return EEM_Event
898
+	 * @throws EE_Error
899
+	 * @throws InvalidArgumentException
900
+	 * @throws InvalidDataTypeException
901
+	 * @throws InvalidInterfaceException
902
+	 * @throws ReflectionException
903
+	 */
904
+	private function _event_model()
905
+	{
906
+		if (! $this->_event_model instanceof EEM_Event) {
907
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
908
+		}
909
+		return $this->_event_model;
910
+	}
911
+
912
+
913
+	/**
914
+	 * Adds extra buttons to the WP CPT permalink field row.
915
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
916
+	 *
917
+	 * @param  string $return    the current html
918
+	 * @param  int    $id        the post id for the page
919
+	 * @param  string $new_title What the title is
920
+	 * @param  string $new_slug  what the slug is
921
+	 * @return string            The new html string for the permalink area
922
+	 */
923
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
924
+	{
925
+		// make sure this is only when editing
926
+		if (! empty($id)) {
927
+			$post = get_post($id);
928
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
929
+					   . esc_html__('Shortcode', 'event_espresso')
930
+					   . '</a> ';
931
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
932
+					   . $post->ID
933
+					   . ']">';
934
+		}
935
+		return $return;
936
+	}
937
+
938
+
939
+	/**
940
+	 * _events_overview_list_table
941
+	 * This contains the logic for showing the events_overview list
942
+	 *
943
+	 * @access protected
944
+	 * @return void
945
+	 * @throws DomainException
946
+	 * @throws EE_Error
947
+	 * @throws InvalidArgumentException
948
+	 * @throws InvalidDataTypeException
949
+	 * @throws InvalidInterfaceException
950
+	 */
951
+	protected function _events_overview_list_table()
952
+	{
953
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
954
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
955
+			? (array) $this->_template_args['after_list_table']
956
+			: array();
957
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
958
+				. EEH_Template::get_button_or_link(
959
+					get_post_type_archive_link('espresso_events'),
960
+					esc_html__('View Event Archive Page', 'event_espresso'),
961
+					'button'
962
+				);
963
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
964
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
965
+			'create_new',
966
+			'add',
967
+			array(),
968
+			'add-new-h2'
969
+		);
970
+		$this->display_admin_list_table_page_with_no_sidebar();
971
+	}
972
+
973
+
974
+	/**
975
+	 * this allows for extra misc actions in the default WP publish box
976
+	 *
977
+	 * @return void
978
+	 * @throws DomainException
979
+	 * @throws EE_Error
980
+	 * @throws InvalidArgumentException
981
+	 * @throws InvalidDataTypeException
982
+	 * @throws InvalidInterfaceException
983
+	 * @throws ReflectionException
984
+	 */
985
+	public function extra_misc_actions_publish_box()
986
+	{
987
+		$this->_generate_publish_box_extra_content();
988
+	}
989
+
990
+
991
+	/**
992
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
993
+	 * saved.
994
+	 * Typically you would use this to save any additional data.
995
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
996
+	 * ALSO very important.  When a post transitions from scheduled to published,
997
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
998
+	 * other meta saves. So MAKE sure that you handle this accordingly.
999
+	 *
1000
+	 * @access protected
1001
+	 * @abstract
1002
+	 * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
1003
+	 * @param object $post    The post object of the cpt that was saved.
1004
+	 * @return void
1005
+	 * @throws EE_Error
1006
+	 * @throws InvalidArgumentException
1007
+	 * @throws InvalidDataTypeException
1008
+	 * @throws InvalidInterfaceException
1009
+	 * @throws ReflectionException
1010
+	 */
1011
+	protected function _insert_update_cpt_item($post_id, $post)
1012
+	{
1013
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1014
+			// get out we're not processing an event save.
1015
+			return;
1016
+		}
1017
+		$event_values = array(
1018
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1019
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1020
+			'EVT_additional_limit'            => min(
1021
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1022
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1023
+			),
1024
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1025
+				? $this->_req_data['EVT_default_registration_status']
1026
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
1027
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1028
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1029
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1030
+				? $this->_req_data['timezone_string'] : null,
1031
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1032
+				? $this->_req_data['externalURL'] : null,
1033
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1034
+				? $this->_req_data['event_phone'] : null,
1035
+		);
1036
+		// update event
1037
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1038
+		// get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1039
+		$get_one_where = array(
1040
+			$this->_event_model()->primary_key_name() => $post_id,
1041
+			'OR'                                      => array(
1042
+				'status'   => $post->post_status,
1043
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1044
+				// but the returned object here has a status of "publish", so use the original post status as well
1045
+				'status*1' => $this->_req_data['original_post_status'],
1046
+			),
1047
+		);
1048
+		$event = $this->_event_model()->get_one(array($get_one_where));
1049
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1050
+		$event_update_callbacks = apply_filters(
1051
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1052
+			array(
1053
+				array($this, '_default_venue_update'),
1054
+				array($this, '_default_tickets_update'),
1055
+			)
1056
+		);
1057
+		$att_success = true;
1058
+		foreach ($event_update_callbacks as $e_callback) {
1059
+			$_success = is_callable($e_callback)
1060
+				? $e_callback($event, $this->_req_data)
1061
+				: false;
1062
+			// if ANY of these updates fail then we want the appropriate global error message
1063
+			$att_success = ! $att_success ? $att_success : $_success;
1064
+		}
1065
+		// any errors?
1066
+		if ($success && false === $att_success) {
1067
+			EE_Error::add_error(
1068
+				esc_html__(
1069
+					'Event Details saved successfully but something went wrong with saving attachments.',
1070
+					'event_espresso'
1071
+				),
1072
+				__FILE__,
1073
+				__FUNCTION__,
1074
+				__LINE__
1075
+			);
1076
+		} elseif ($success === false) {
1077
+			EE_Error::add_error(
1078
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1079
+				__FILE__,
1080
+				__FUNCTION__,
1081
+				__LINE__
1082
+			);
1083
+		}
1084
+	}
1085
+
1086
+
1087
+	/**
1088
+	 * @param int $post_id
1089
+	 * @param int $revision_id
1090
+	 * @throws EE_Error
1091
+	 * @throws InvalidArgumentException
1092
+	 * @throws InvalidDataTypeException
1093
+	 * @throws InvalidInterfaceException
1094
+	 * @throws ReflectionException
1095
+	 * @see parent::restore_item()
1096
+	 */
1097
+	protected function _restore_cpt_item($post_id, $revision_id)
1098
+	{
1099
+		// copy existing event meta to new post
1100
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1101
+		if ($post_evt instanceof EE_Event) {
1102
+			// meta revision restore
1103
+			$post_evt->restore_revision($revision_id);
1104
+			// related objs restore
1105
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1106
+		}
1107
+	}
1108
+
1109
+
1110
+	/**
1111
+	 * Attach the venue to the Event
1112
+	 *
1113
+	 * @param EE_Event $evtobj Event Object to add the venue to
1114
+	 * @param array    $data   The request data from the form
1115
+	 * @return bool           Success or fail.
1116
+	 * @throws EE_Error
1117
+	 * @throws InvalidArgumentException
1118
+	 * @throws InvalidDataTypeException
1119
+	 * @throws InvalidInterfaceException
1120
+	 * @throws ReflectionException
1121
+	 */
1122
+	protected function _default_venue_update(EE_Event $evtobj, $data)
1123
+	{
1124
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1125
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1126
+		$rows_affected = null;
1127
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1128
+		// very important.  If we don't have a venue name...
1129
+		// then we'll get out because not necessary to create empty venue
1130
+		if (empty($data['venue_title'])) {
1131
+			return false;
1132
+		}
1133
+		$venue_array = array(
1134
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1135
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1136
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1137
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1138
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1139
+				: null,
1140
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1141
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1142
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1143
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1144
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1145
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1146
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1147
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1148
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1149
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1150
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1151
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1152
+			'status'              => 'publish',
1153
+		);
1154
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1155
+		if (! empty($venue_id)) {
1156
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1157
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1158
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1159
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1160
+			return $rows_affected > 0;
1161
+		}
1162
+		// we insert the venue
1163
+		$venue_id = $venue_model->insert($venue_array);
1164
+		$evtobj->_add_relation_to($venue_id, 'Venue');
1165
+		return ! empty($venue_id) ? true : false;
1166
+		// when we have the ancestor come in it's already been handled by the revision save.
1167
+	}
1168
+
1169
+
1170
+	/**
1171
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1172
+	 *
1173
+	 * @param EE_Event $evtobj The Event object we're attaching data to
1174
+	 * @param array    $data   The request data from the form
1175
+	 * @return array
1176
+	 * @throws EE_Error
1177
+	 * @throws InvalidArgumentException
1178
+	 * @throws InvalidDataTypeException
1179
+	 * @throws InvalidInterfaceException
1180
+	 * @throws ReflectionException
1181
+	 * @throws Exception
1182
+	 */
1183
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1184
+	{
1185
+		if ($this->admin_config->useAdvancedEditor()) {
1186
+			return [];
1187
+		}
1188
+		$success = true;
1189
+		$saved_dtt = null;
1190
+		$saved_tickets = array();
1191
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1192
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1193
+			// trim all values to ensure any excess whitespace is removed.
1194
+			$dtt = array_map('trim', $dtt);
1195
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1196
+				: $dtt['DTT_EVT_start'];
1197
+			$datetime_values = array(
1198
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1199
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1200
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1201
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1202
+				'DTT_order'     => $row,
1203
+			);
1204
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1205
+			if (! empty($dtt['DTT_ID'])) {
1206
+				$DTM = EE_Registry::instance()
1207
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1208
+								  ->get_one_by_ID($dtt['DTT_ID']);
1209
+				$DTM->set_date_format($incoming_date_formats[0]);
1210
+				$DTM->set_time_format($incoming_date_formats[1]);
1211
+				foreach ($datetime_values as $field => $value) {
1212
+					$DTM->set($field, $value);
1213
+				}
1214
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1215
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1216
+			} else {
1217
+				$DTM = EE_Registry::instance()->load_class(
1218
+					'Datetime',
1219
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1220
+					false,
1221
+					false
1222
+				);
1223
+				foreach ($datetime_values as $field => $value) {
1224
+					$DTM->set($field, $value);
1225
+				}
1226
+			}
1227
+			$DTM->save();
1228
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1229
+			// load DTT helper
1230
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1231
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1232
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1233
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1234
+				$DTT->save();
1235
+			}
1236
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1237
+			$saved_dtt = $DTT;
1238
+			$success = ! $success ? $success : $DTT;
1239
+			// if ANY of these updates fail then we want the appropriate global error message.
1240
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1241
+		}
1242
+		// no dtts get deleted so we don't do any of that logic here.
1243
+		// update tickets next
1244
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1245
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1246
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1247
+			$update_prices = false;
1248
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1249
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1250
+			// trim inputs to ensure any excess whitespace is removed.
1251
+			$tkt = array_map('trim', $tkt);
1252
+			if (empty($tkt['TKT_start_date'])) {
1253
+				// let's use now in the set timezone.
1254
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1255
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1256
+			}
1257
+			if (empty($tkt['TKT_end_date'])) {
1258
+				// use the start date of the first datetime
1259
+				$dtt = $evtobj->first_datetime();
1260
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1261
+					$incoming_date_formats[0],
1262
+					$incoming_date_formats[1]
1263
+				);
1264
+			}
1265
+			$TKT_values = array(
1266
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1267
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1268
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1269
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1270
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1271
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1272
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1273
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1274
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1275
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1276
+				'TKT_row'         => $row,
1277
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1278
+				'TKT_price'       => $ticket_price,
1279
+			);
1280
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1281
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1282
+				$TKT_values['TKT_ID'] = 0;
1283
+				$TKT_values['TKT_is_default'] = 0;
1284
+				$TKT_values['TKT_price'] = $ticket_price;
1285
+				$update_prices = true;
1286
+			}
1287
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1288
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1289
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1290
+			if (! empty($tkt['TKT_ID'])) {
1291
+				$TKT = EE_Registry::instance()
1292
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1293
+								  ->get_one_by_ID($tkt['TKT_ID']);
1294
+				if ($TKT instanceof EE_Ticket) {
1295
+					$ticket_sold = $TKT->count_related(
1296
+						'Registration',
1297
+						array(
1298
+							array(
1299
+								'STS_ID' => array(
1300
+									'NOT IN',
1301
+									array(EEM_Registration::status_id_incomplete),
1302
+								),
1303
+							),
1304
+						)
1305
+					) > 0;
1306
+					// let's just check the total price for the existing ticket and determine if it matches the new
1307
+					// total price.  if they are different then we create a new ticket (if tickets sold)
1308
+					// if they aren't different then we go ahead and modify existing ticket.
1309
+					$create_new_TKT = $ticket_sold && ! $TKT->deleted() && EEH_Money::compare_floats(
1310
+						$ticket_price,
1311
+						$TKT->get('TKT_price'),
1312
+						'!=='
1313
+					);
1314
+					$TKT->set_date_format($incoming_date_formats[0]);
1315
+					$TKT->set_time_format($incoming_date_formats[1]);
1316
+					// set new values
1317
+					foreach ($TKT_values as $field => $value) {
1318
+						if ($field === 'TKT_qty') {
1319
+							$TKT->set_qty($value);
1320
+						} else {
1321
+							$TKT->set($field, $value);
1322
+						}
1323
+					}
1324
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1325
+					if ($create_new_TKT) {
1326
+						// archive the old ticket first
1327
+						$TKT->set('TKT_deleted', 1);
1328
+						$TKT->save();
1329
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1330
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1331
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1332
+						$TKT = clone $TKT;
1333
+						$TKT->set('TKT_ID', 0);
1334
+						$TKT->set('TKT_deleted', 0);
1335
+						$TKT->set('TKT_price', $ticket_price);
1336
+						$TKT->set('TKT_sold', 0);
1337
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1338
+						$update_prices = true;
1339
+					}
1340
+					// make sure price is set if it hasn't been already
1341
+					$TKT->set('TKT_price', $ticket_price);
1342
+				}
1343
+			} else {
1344
+				// no TKT_id so a new TKT
1345
+				$TKT_values['TKT_price'] = $ticket_price;
1346
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1347
+				if ($TKT instanceof EE_Ticket) {
1348
+					// need to reset values to properly account for the date formats
1349
+					$TKT->set_date_format($incoming_date_formats[0]);
1350
+					$TKT->set_time_format($incoming_date_formats[1]);
1351
+					$TKT->set_timezone($evtobj->get_timezone());
1352
+					// set new values
1353
+					foreach ($TKT_values as $field => $value) {
1354
+						if ($field === 'TKT_qty') {
1355
+							$TKT->set_qty($value);
1356
+						} else {
1357
+							$TKT->set($field, $value);
1358
+						}
1359
+					}
1360
+					$update_prices = true;
1361
+				}
1362
+			}
1363
+			// cap ticket qty by datetime reg limits
1364
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1365
+			// update ticket.
1366
+			$TKT->save();
1367
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1368
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1369
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1370
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1371
+				$TKT->save();
1372
+			}
1373
+			// initially let's add the ticket to the dtt
1374
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1375
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1376
+			// add prices to ticket
1377
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1378
+		}
1379
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1380
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
1381
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1382
+		foreach ($tickets_removed as $id) {
1383
+			$id = absint($id);
1384
+			// get the ticket for this id
1385
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1386
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1387
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1388
+			foreach ($dtts as $dtt) {
1389
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1390
+			}
1391
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1392
+			$tkt_to_remove->delete_related_permanently('Price');
1393
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1394
+			$tkt_to_remove->delete_permanently();
1395
+		}
1396
+		return array($saved_dtt, $saved_tickets);
1397
+	}
1398
+
1399
+
1400
+	/**
1401
+	 * This attaches a list of given prices to a ticket.
1402
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1403
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1404
+	 * price info and prices are automatically "archived" via the ticket.
1405
+	 *
1406
+	 * @access  private
1407
+	 * @param array     $prices     Array of prices from the form.
1408
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1409
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1410
+	 * @return  void
1411
+	 * @throws EE_Error
1412
+	 * @throws InvalidArgumentException
1413
+	 * @throws InvalidDataTypeException
1414
+	 * @throws InvalidInterfaceException
1415
+	 * @throws ReflectionException
1416
+	 */
1417
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1418
+	{
1419
+		foreach ($prices as $row => $prc) {
1420
+			$PRC_values = array(
1421
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1422
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1423
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1424
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1425
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1426
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1427
+				'PRC_order'      => $row,
1428
+			);
1429
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1430
+				$PRC_values['PRC_ID'] = 0;
1431
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1432
+			} else {
1433
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1434
+				// update this price with new values
1435
+				foreach ($PRC_values as $field => $newprc) {
1436
+					$PRC->set($field, $newprc);
1437
+				}
1438
+				$PRC->save();
1439
+			}
1440
+			$ticket->_add_relation_to($PRC, 'Price');
1441
+		}
1442
+	}
1443
+
1444
+
1445
+	/**
1446
+	 * Add in our autosave ajax handlers
1447
+	 *
1448
+	 */
1449
+	protected function _ee_autosave_create_new()
1450
+	{
1451
+	}
1452
+
1453
+
1454
+	/**
1455
+	 * More autosave handlers.
1456
+	 */
1457
+	protected function _ee_autosave_edit()
1458
+	{
1459
+	}
1460
+
1461
+
1462
+	/**
1463
+	 *    _generate_publish_box_extra_content
1464
+	 *
1465
+	 * @throws DomainException
1466
+	 * @throws EE_Error
1467
+	 * @throws InvalidArgumentException
1468
+	 * @throws InvalidDataTypeException
1469
+	 * @throws InvalidInterfaceException
1470
+	 * @throws ReflectionException
1471
+	 */
1472
+	private function _generate_publish_box_extra_content()
1473
+	{
1474
+		// load formatter helper
1475
+		// args for getting related registrations
1476
+		$approved_query_args = array(
1477
+			array(
1478
+				'REG_deleted' => 0,
1479
+				'STS_ID'      => EEM_Registration::status_id_approved,
1480
+			),
1481
+		);
1482
+		$not_approved_query_args = array(
1483
+			array(
1484
+				'REG_deleted' => 0,
1485
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1486
+			),
1487
+		);
1488
+		$pending_payment_query_args = array(
1489
+			array(
1490
+				'REG_deleted' => 0,
1491
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1492
+			),
1493
+		);
1494
+		// publish box
1495
+		$publish_box_extra_args = array(
1496
+			'view_approved_reg_url'        => add_query_arg(
1497
+				array(
1498
+					'action'      => 'default',
1499
+					'event_id'    => $this->_cpt_model_obj->ID(),
1500
+					'_reg_status' => EEM_Registration::status_id_approved,
1501
+				),
1502
+				REG_ADMIN_URL
1503
+			),
1504
+			'view_not_approved_reg_url'    => add_query_arg(
1505
+				array(
1506
+					'action'      => 'default',
1507
+					'event_id'    => $this->_cpt_model_obj->ID(),
1508
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1509
+				),
1510
+				REG_ADMIN_URL
1511
+			),
1512
+			'view_pending_payment_reg_url' => add_query_arg(
1513
+				array(
1514
+					'action'      => 'default',
1515
+					'event_id'    => $this->_cpt_model_obj->ID(),
1516
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1517
+				),
1518
+				REG_ADMIN_URL
1519
+			),
1520
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1521
+				'Registration',
1522
+				$approved_query_args
1523
+			),
1524
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1525
+				'Registration',
1526
+				$not_approved_query_args
1527
+			),
1528
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1529
+				'Registration',
1530
+				$pending_payment_query_args
1531
+			),
1532
+			'misc_pub_section_class'       => apply_filters(
1533
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1534
+				'misc-pub-section'
1535
+			),
1536
+		);
1537
+		ob_start();
1538
+		do_action(
1539
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1540
+			$this->_cpt_model_obj
1541
+		);
1542
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1543
+		// load template
1544
+		EEH_Template::display_template(
1545
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1546
+			$publish_box_extra_args
1547
+		);
1548
+	}
1549
+
1550
+
1551
+	/**
1552
+	 * @return EE_Event
1553
+	 */
1554
+	public function get_event_object()
1555
+	{
1556
+		return $this->_cpt_model_obj;
1557
+	}
1558
+
1559
+
1560
+
1561
+
1562
+	/** METABOXES * */
1563
+	/**
1564
+	 * _register_event_editor_meta_boxes
1565
+	 * add all metaboxes related to the event_editor
1566
+	 *
1567
+	 * @return void
1568
+	 * @throws EE_Error
1569
+	 * @throws InvalidArgumentException
1570
+	 * @throws InvalidDataTypeException
1571
+	 * @throws InvalidInterfaceException
1572
+	 * @throws ReflectionException
1573
+	 */
1574
+	protected function _register_event_editor_meta_boxes()
1575
+	{
1576
+		$this->verify_cpt_object();
1577
+		if ($this->admin_config->useAdvancedEditor()) {
1578
+			add_action(
1579
+				'add_meta_boxes_espresso_events',
1580
+				function () {
1581
+					global $current_screen;
1582
+					remove_meta_box('authordiv', $current_screen, 'normal');
1583
+				},
1584
+				99
1585
+			);
1586
+			return;
1587
+		}
1588
+		add_meta_box(
1589
+			'espresso_event_editor_tickets',
1590
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1591
+			[$this, 'ticket_metabox'],
1592
+			$this->page_slug,
1593
+			'normal',
1594
+			'high'
1595
+		);
1596
+		add_meta_box(
1597
+			'espresso_event_editor_event_options',
1598
+			esc_html__('Event Registration Options', 'event_espresso'),
1599
+			array($this, 'registration_options_meta_box'),
1600
+			$this->page_slug,
1601
+			'side'
1602
+		);
1603
+		// NOTE: if you're looking for other metaboxes in here,
1604
+		// where a metabox has a related management page in the admin
1605
+		// you will find it setup in the related management page's "_Hooks" file.
1606
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1607
+	}
1608
+
1609
+
1610
+	/**
1611
+	 * @throws DomainException
1612
+	 * @throws EE_Error
1613
+	 * @throws InvalidArgumentException
1614
+	 * @throws InvalidDataTypeException
1615
+	 * @throws InvalidInterfaceException
1616
+	 * @throws ReflectionException
1617
+	 */
1618
+	public function ticket_metabox()
1619
+	{
1620
+		$existing_datetime_ids = $existing_ticket_ids = array();
1621
+		// defaults for template args
1622
+		$template_args = array(
1623
+			'existing_datetime_ids'    => '',
1624
+			'event_datetime_help_link' => '',
1625
+			'ticket_options_help_link' => '',
1626
+			'time'                     => null,
1627
+			'ticket_rows'              => '',
1628
+			'existing_ticket_ids'      => '',
1629
+			'total_ticket_rows'        => 1,
1630
+			'ticket_js_structure'      => '',
1631
+			'trash_icon'               => 'ee-lock-icon',
1632
+			'disabled'                 => '',
1633
+		);
1634
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1635
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1636
+		/**
1637
+		 * 1. Start with retrieving Datetimes
1638
+		 * 2. Fore each datetime get related tickets
1639
+		 * 3. For each ticket get related prices
1640
+		 */
1641
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1642
+		/** @type EE_Datetime $first_datetime */
1643
+		$first_datetime = reset($times);
1644
+		// do we get related tickets?
1645
+		if ($first_datetime instanceof EE_Datetime
1646
+			&& $first_datetime->ID() !== 0
1647
+		) {
1648
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1649
+			$template_args['time'] = $first_datetime;
1650
+			$related_tickets = $first_datetime->tickets(
1651
+				array(
1652
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1653
+					'default_where_conditions' => 'none',
1654
+				)
1655
+			);
1656
+			if (! empty($related_tickets)) {
1657
+				$template_args['total_ticket_rows'] = count($related_tickets);
1658
+				$row = 0;
1659
+				foreach ($related_tickets as $ticket) {
1660
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1661
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1662
+					$row++;
1663
+				}
1664
+			} else {
1665
+				$template_args['total_ticket_rows'] = 1;
1666
+				/** @type EE_Ticket $ticket */
1667
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1668
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1669
+			}
1670
+		} else {
1671
+			$template_args['time'] = $times[0];
1672
+			/** @type EE_Ticket $ticket */
1673
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1674
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1675
+			// NOTE: we're just sending the first default row
1676
+			// (decaf can't manage default tickets so this should be sufficient);
1677
+		}
1678
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1679
+			'event_editor_event_datetimes_help_tab'
1680
+		);
1681
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1682
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1683
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1684
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1685
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1686
+			true
1687
+		);
1688
+		$template = apply_filters(
1689
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1690
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1691
+		);
1692
+		EEH_Template::display_template($template, $template_args);
1693
+	}
1694
+
1695
+
1696
+	/**
1697
+	 * Setup an individual ticket form for the decaf event editor page
1698
+	 *
1699
+	 * @access private
1700
+	 * @param EE_Ticket $ticket   the ticket object
1701
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1702
+	 * @param int       $row
1703
+	 * @return string generated html for the ticket row.
1704
+	 * @throws DomainException
1705
+	 * @throws EE_Error
1706
+	 * @throws InvalidArgumentException
1707
+	 * @throws InvalidDataTypeException
1708
+	 * @throws InvalidInterfaceException
1709
+	 * @throws ReflectionException
1710
+	 */
1711
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1712
+	{
1713
+		$template_args = array(
1714
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1715
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1716
+				: '',
1717
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1718
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1719
+			'TKT_name'            => $ticket->get('TKT_name'),
1720
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1721
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1722
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1723
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1724
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1725
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1726
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1727
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1728
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1729
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1730
+				: ' disabled=disabled',
1731
+		);
1732
+		$price = $ticket->ID() !== 0
1733
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1734
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1735
+		$price_args = array(
1736
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1737
+			'PRC_amount'            => $price->get('PRC_amount'),
1738
+			'PRT_ID'                => $price->get('PRT_ID'),
1739
+			'PRC_ID'                => $price->get('PRC_ID'),
1740
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1741
+		);
1742
+		// make sure we have default start and end dates if skeleton
1743
+		// handle rows that should NOT be empty
1744
+		if (empty($template_args['TKT_start_date'])) {
1745
+			// if empty then the start date will be now.
1746
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1747
+		}
1748
+		if (empty($template_args['TKT_end_date'])) {
1749
+			// get the earliest datetime (if present);
1750
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1751
+				? $this->_cpt_model_obj->get_first_related(
1752
+					'Datetime',
1753
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1754
+				)
1755
+				: null;
1756
+			if (! empty($earliest_dtt)) {
1757
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1758
+			} else {
1759
+				$template_args['TKT_end_date'] = date(
1760
+					'Y-m-d h:i a',
1761
+					mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1762
+				);
1763
+			}
1764
+		}
1765
+		$template_args = array_merge($template_args, $price_args);
1766
+		$template = apply_filters(
1767
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1768
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1769
+			$ticket
1770
+		);
1771
+		return EEH_Template::display_template($template, $template_args, true);
1772
+	}
1773
+
1774
+
1775
+	/**
1776
+	 * @throws DomainException
1777
+	 * @throws EE_Error
1778
+	 */
1779
+	public function registration_options_meta_box()
1780
+	{
1781
+		$yes_no_values = array(
1782
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1783
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1784
+		);
1785
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1786
+			array(
1787
+				EEM_Registration::status_id_cancelled,
1788
+				EEM_Registration::status_id_declined,
1789
+				EEM_Registration::status_id_incomplete,
1790
+			),
1791
+			true
1792
+		);
1793
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1794
+		$template_args['_event'] = $this->_cpt_model_obj;
1795
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1796
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1797
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1798
+			'default_reg_status',
1799
+			$default_reg_status_values,
1800
+			$this->_cpt_model_obj->default_registration_status()
1801
+		);
1802
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1803
+			'display_desc',
1804
+			$yes_no_values,
1805
+			$this->_cpt_model_obj->display_description()
1806
+		);
1807
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1808
+			'display_ticket_selector',
1809
+			$yes_no_values,
1810
+			$this->_cpt_model_obj->display_ticket_selector(),
1811
+			'',
1812
+			'',
1813
+			false
1814
+		);
1815
+		$template_args['additional_registration_options'] = apply_filters(
1816
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1817
+			'',
1818
+			$template_args,
1819
+			$yes_no_values,
1820
+			$default_reg_status_values
1821
+		);
1822
+		EEH_Template::display_template(
1823
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1824
+			$template_args
1825
+		);
1826
+	}
1827
+
1828
+
1829
+	/**
1830
+	 * _get_events()
1831
+	 * This method simply returns all the events (for the given _view and paging)
1832
+	 *
1833
+	 * @access public
1834
+	 * @param int  $per_page     count of items per page (20 default);
1835
+	 * @param int  $current_page what is the current page being viewed.
1836
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1837
+	 *                           If FALSE then we return an array of event objects
1838
+	 *                           that match the given _view and paging parameters.
1839
+	 * @return array an array of event objects.
1840
+	 * @throws EE_Error
1841
+	 * @throws InvalidArgumentException
1842
+	 * @throws InvalidDataTypeException
1843
+	 * @throws InvalidInterfaceException
1844
+	 * @throws ReflectionException
1845
+	 * @throws Exception
1846
+	 * @throws Exception
1847
+	 * @throws Exception
1848
+	 */
1849
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1850
+	{
1851
+		$EEME = $this->_event_model();
1852
+		$offset = ($current_page - 1) * $per_page;
1853
+		$limit = $count ? null : $offset . ',' . $per_page;
1854
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1855
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1856
+		if (isset($this->_req_data['month_range'])) {
1857
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1858
+			// simulate the FIRST day of the month, that fixes issues for months like February
1859
+			// where PHP doesn't know what to assume for date.
1860
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1861
+			$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1862
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1863
+		}
1864
+		$where = array();
1865
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1866
+		// determine what post_status our condition will have for the query.
1867
+		switch ($status) {
1868
+			case 'month':
1869
+			case 'today':
1870
+			case null:
1871
+			case 'all':
1872
+				break;
1873
+			case 'draft':
1874
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1875
+				break;
1876
+			default:
1877
+				$where['status'] = $status;
1878
+		}
1879
+		// categories?
1880
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1881
+			? $this->_req_data['EVT_CAT'] : null;
1882
+		if (! empty($category)) {
1883
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1884
+			$where['Term_Taxonomy.term_id'] = $category;
1885
+		}
1886
+		// date where conditions
1887
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1888
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1889
+			$DateTime = new DateTime(
1890
+				$year_r . '-' . $month_r . '-01 00:00:00',
1891
+				new DateTimeZone('UTC')
1892
+			);
1893
+			$start = $DateTime->getTimestamp();
1894
+			// set the datetime to be the end of the month
1895
+			$DateTime->setDate(
1896
+				$year_r,
1897
+				$month_r,
1898
+				$DateTime->format('t')
1899
+			)->setTime(23, 59, 59);
1900
+			$end = $DateTime->getTimestamp();
1901
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1902
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1903
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1904
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1905
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1906
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1907
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1908
+			$now = date('Y-m-01');
1909
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1910
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1911
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1912
+							->setTime(23, 59, 59)
1913
+							->format(implode(' ', $start_formats));
1914
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1915
+		}
1916
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1917
+			$where['EVT_wp_user'] = get_current_user_id();
1918
+		} elseif (! isset($where['status'])
1919
+			&& ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1920
+		) {
1921
+			$where['OR'] = array(
1922
+				'status*restrict_private' => array('!=', 'private'),
1923
+				'AND'                     => array(
1924
+					'status*inclusive' => array('=', 'private'),
1925
+					'EVT_wp_user'      => get_current_user_id(),
1926
+				),
1927
+			);
1928
+		}
1929
+
1930
+		if (isset($this->_req_data['EVT_wp_user'])
1931
+			&& (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
1932
+			&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1933
+		) {
1934
+			$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1935
+		}
1936
+		// search query handling
1937
+		if (isset($this->_req_data['s'])) {
1938
+			$search_string = '%' . $this->_req_data['s'] . '%';
1939
+			$where['OR'] = array(
1940
+				'EVT_name'       => array('LIKE', $search_string),
1941
+				'EVT_desc'       => array('LIKE', $search_string),
1942
+				'EVT_short_desc' => array('LIKE', $search_string),
1943
+			);
1944
+		}
1945
+		// filter events by venue.
1946
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1947
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1948
+		}
1949
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1950
+		$query_params = apply_filters(
1951
+			'FHEE__Events_Admin_Page__get_events__query_params',
1952
+			array(
1953
+				$where,
1954
+				'limit'    => $limit,
1955
+				'order_by' => $orderby,
1956
+				'order'    => $order,
1957
+				'group_by' => 'EVT_ID',
1958
+			),
1959
+			$this->_req_data
1960
+		);
1961
+
1962
+		// let's first check if we have special requests coming in.
1963
+		if (isset($this->_req_data['active_status'])) {
1964
+			switch ($this->_req_data['active_status']) {
1965
+				case 'upcoming':
1966
+					return $EEME->get_upcoming_events($query_params, $count);
1967
+					break;
1968
+				case 'expired':
1969
+					return $EEME->get_expired_events($query_params, $count);
1970
+					break;
1971
+				case 'active':
1972
+					return $EEME->get_active_events($query_params, $count);
1973
+					break;
1974
+				case 'inactive':
1975
+					return $EEME->get_inactive_events($query_params, $count);
1976
+					break;
1977
+			}
1978
+		}
1979
+
1980
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1981
+		return $events;
1982
+	}
1983
+
1984
+
1985
+	/**
1986
+	 * handling for WordPress CPT actions (trash, restore, delete)
1987
+	 *
1988
+	 * @param string $post_id
1989
+	 * @throws EE_Error
1990
+	 * @throws InvalidArgumentException
1991
+	 * @throws InvalidDataTypeException
1992
+	 * @throws InvalidInterfaceException
1993
+	 * @throws ReflectionException
1994
+	 */
1995
+	public function trash_cpt_item($post_id)
1996
+	{
1997
+		$this->_req_data['EVT_ID'] = $post_id;
1998
+		$this->_trash_or_restore_event('trash', false);
1999
+	}
2000
+
2001
+
2002
+	/**
2003
+	 * @param string $post_id
2004
+	 * @throws EE_Error
2005
+	 * @throws InvalidArgumentException
2006
+	 * @throws InvalidDataTypeException
2007
+	 * @throws InvalidInterfaceException
2008
+	 * @throws ReflectionException
2009
+	 */
2010
+	public function restore_cpt_item($post_id)
2011
+	{
2012
+		$this->_req_data['EVT_ID'] = $post_id;
2013
+		$this->_trash_or_restore_event('draft', false);
2014
+	}
2015
+
2016
+
2017
+	/**
2018
+	 * @param string $post_id
2019
+	 * @throws EE_Error
2020
+	 * @throws InvalidArgumentException
2021
+	 * @throws InvalidDataTypeException
2022
+	 * @throws InvalidInterfaceException
2023
+	 * @throws ReflectionException
2024
+	 */
2025
+	public function delete_cpt_item($post_id)
2026
+	{
2027
+		$this->_req_data['EVT_ID'] = $post_id;
2028
+		$this->_delete_event(false);
2029
+	}
2030
+
2031
+
2032
+	/**
2033
+	 * _trash_or_restore_event
2034
+	 *
2035
+	 * @access protected
2036
+	 * @param string $event_status
2037
+	 * @param bool   $redirect_after
2038
+	 * @throws EE_Error
2039
+	 * @throws InvalidArgumentException
2040
+	 * @throws InvalidDataTypeException
2041
+	 * @throws InvalidInterfaceException
2042
+	 * @throws ReflectionException
2043
+	 */
2044
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2045
+	{
2046
+		// determine the event id and set to array.
2047
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2048
+		// loop thru events
2049
+		if ($EVT_ID) {
2050
+			// clean status
2051
+			$event_status = sanitize_key($event_status);
2052
+			// grab status
2053
+			if (! empty($event_status)) {
2054
+				$success = $this->_change_event_status($EVT_ID, $event_status);
2055
+			} else {
2056
+				$success = false;
2057
+				$msg = esc_html__(
2058
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2059
+					'event_espresso'
2060
+				);
2061
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2062
+			}
2063
+		} else {
2064
+			$success = false;
2065
+			$msg = esc_html__(
2066
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2067
+				'event_espresso'
2068
+			);
2069
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2070
+		}
2071
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2072
+		if ($redirect_after) {
2073
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
2074
+		}
2075
+	}
2076
+
2077
+
2078
+	/**
2079
+	 * _trash_or_restore_events
2080
+	 *
2081
+	 * @access protected
2082
+	 * @param string $event_status
2083
+	 * @return void
2084
+	 * @throws EE_Error
2085
+	 * @throws InvalidArgumentException
2086
+	 * @throws InvalidDataTypeException
2087
+	 * @throws InvalidInterfaceException
2088
+	 * @throws ReflectionException
2089
+	 */
2090
+	protected function _trash_or_restore_events($event_status = 'trash')
2091
+	{
2092
+		// clean status
2093
+		$event_status = sanitize_key($event_status);
2094
+		// grab status
2095
+		if (! empty($event_status)) {
2096
+			$success = true;
2097
+			// determine the event id and set to array.
2098
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2099
+			// loop thru events
2100
+			foreach ($EVT_IDs as $EVT_ID) {
2101
+				if ($EVT_ID = absint($EVT_ID)) {
2102
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2103
+					$success = $results !== false ? $success : false;
2104
+				} else {
2105
+					$msg = sprintf(
2106
+						esc_html__(
2107
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2108
+							'event_espresso'
2109
+						),
2110
+						$EVT_ID
2111
+					);
2112
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2113
+					$success = false;
2114
+				}
2115
+			}
2116
+		} else {
2117
+			$success = false;
2118
+			$msg = esc_html__(
2119
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2120
+				'event_espresso'
2121
+			);
2122
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2123
+		}
2124
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2125
+		$success = $success ? 2 : false;
2126
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2127
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2128
+	}
2129
+
2130
+
2131
+	/**
2132
+	 * _trash_or_restore_events
2133
+	 *
2134
+	 * @access  private
2135
+	 * @param int    $EVT_ID
2136
+	 * @param string $event_status
2137
+	 * @return bool
2138
+	 * @throws EE_Error
2139
+	 * @throws InvalidArgumentException
2140
+	 * @throws InvalidDataTypeException
2141
+	 * @throws InvalidInterfaceException
2142
+	 * @throws ReflectionException
2143
+	 */
2144
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2145
+	{
2146
+		// grab event id
2147
+		if (! $EVT_ID) {
2148
+			$msg = esc_html__(
2149
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2150
+				'event_espresso'
2151
+			);
2152
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2153
+			return false;
2154
+		}
2155
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2156
+		// clean status
2157
+		$event_status = sanitize_key($event_status);
2158
+		// grab status
2159
+		if (empty($event_status)) {
2160
+			$msg = esc_html__(
2161
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2162
+				'event_espresso'
2163
+			);
2164
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2165
+			return false;
2166
+		}
2167
+		// was event trashed or restored ?
2168
+		switch ($event_status) {
2169
+			case 'draft':
2170
+				$action = 'restored from the trash';
2171
+				$hook = 'AHEE_event_restored_from_trash';
2172
+				break;
2173
+			case 'trash':
2174
+				$action = 'moved to the trash';
2175
+				$hook = 'AHEE_event_moved_to_trash';
2176
+				break;
2177
+			default:
2178
+				$action = 'updated';
2179
+				$hook = false;
2180
+		}
2181
+		// use class to change status
2182
+		$this->_cpt_model_obj->set_status($event_status);
2183
+		$success = $this->_cpt_model_obj->save();
2184
+		if ($success === false) {
2185
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2186
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2187
+			return false;
2188
+		}
2189
+		if ($hook) {
2190
+			do_action($hook);
2191
+		}
2192
+		return true;
2193
+	}
2194
+
2195
+
2196
+	/**
2197
+	 * _delete_event
2198
+	 *
2199
+	 * @access protected
2200
+	 * @param bool $redirect_after
2201
+	 * @throws EE_Error
2202
+	 * @throws InvalidArgumentException
2203
+	 * @throws InvalidDataTypeException
2204
+	 * @throws InvalidInterfaceException
2205
+	 * @throws ReflectionException
2206
+	 */
2207
+	protected function _delete_event($redirect_after = true)
2208
+	{
2209
+		// determine the event id and set to array.
2210
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2211
+		$EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2212
+		// loop thru events
2213
+		if ($EVT_ID) {
2214
+			$success = $this->_permanently_delete_event($EVT_ID);
2215
+			// get list of events with no prices
2216
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2217
+			// remove this event from the list of events with no prices
2218
+			if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2219
+				unset($espresso_no_ticket_prices[ $EVT_ID ]);
2220
+			}
2221
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2222
+		} else {
2223
+			$success = false;
2224
+			$msg = esc_html__(
2225
+				'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2226
+				'event_espresso'
2227
+			);
2228
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2229
+		}
2230
+		if ($redirect_after) {
2231
+			$this->_redirect_after_action(
2232
+				$success,
2233
+				'Event',
2234
+				'deleted',
2235
+				array('action' => 'default', 'status' => 'trash')
2236
+			);
2237
+		}
2238
+	}
2239
+
2240
+
2241
+	/**
2242
+	 * _delete_events
2243
+	 *
2244
+	 * @access protected
2245
+	 * @return void
2246
+	 * @throws EE_Error
2247
+	 * @throws InvalidArgumentException
2248
+	 * @throws InvalidDataTypeException
2249
+	 * @throws InvalidInterfaceException
2250
+	 * @throws ReflectionException
2251
+	 */
2252
+	protected function _delete_events()
2253
+	{
2254
+		$success = true;
2255
+		// get list of events with no prices
2256
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2257
+		// determine the event id and set to array.
2258
+		$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2259
+		// loop thru events
2260
+		foreach ($EVT_IDs as $EVT_ID) {
2261
+			$EVT_ID = absint($EVT_ID);
2262
+			if ($EVT_ID) {
2263
+				$results = $this->_permanently_delete_event($EVT_ID);
2264
+				$success = $results !== false ? $success : false;
2265
+				// remove this event from the list of events with no prices
2266
+				unset($espresso_no_ticket_prices[ $EVT_ID ]);
2267
+			} else {
2268
+				$success = false;
2269
+				$msg = esc_html__(
2270
+					'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2271
+					'event_espresso'
2272
+				);
2273
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2274
+			}
2275
+		}
2276
+		update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2277
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2278
+		$success = $success ? 2 : false;
2279
+		$this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2280
+	}
2281
+
2282
+
2283
+	/**
2284
+	 * _permanently_delete_event
2285
+	 *
2286
+	 * @access  private
2287
+	 * @param int $EVT_ID
2288
+	 * @return bool
2289
+	 * @throws EE_Error
2290
+	 * @throws InvalidArgumentException
2291
+	 * @throws InvalidDataTypeException
2292
+	 * @throws InvalidInterfaceException
2293
+	 * @throws ReflectionException
2294
+	 */
2295
+	private function _permanently_delete_event($EVT_ID = 0)
2296
+	{
2297
+		// grab event id
2298
+		if (! $EVT_ID) {
2299
+			$msg = esc_html__(
2300
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2301
+				'event_espresso'
2302
+			);
2303
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2304
+			return false;
2305
+		}
2306
+		if (! $this->_cpt_model_obj instanceof EE_Event
2307
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2308
+		) {
2309
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2310
+		}
2311
+		if (! $this->_cpt_model_obj instanceof EE_Event) {
2312
+			return false;
2313
+		}
2314
+		// need to delete related tickets and prices first.
2315
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2316
+		foreach ($datetimes as $datetime) {
2317
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2318
+			$tickets = $datetime->get_many_related('Ticket');
2319
+			foreach ($tickets as $ticket) {
2320
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2321
+				$ticket->delete_related_permanently('Price');
2322
+				$ticket->delete_permanently();
2323
+			}
2324
+			$datetime->delete();
2325
+		}
2326
+		// what about related venues or terms?
2327
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2328
+		foreach ($venues as $venue) {
2329
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2330
+		}
2331
+		// any attached question groups?
2332
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2333
+		if (! empty($question_groups)) {
2334
+			foreach ($question_groups as $question_group) {
2335
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2336
+			}
2337
+		}
2338
+		// Message Template Groups
2339
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2340
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2341
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2342
+		foreach ($term_taxonomies as $term_taxonomy) {
2343
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2344
+		}
2345
+		$success = $this->_cpt_model_obj->delete_permanently();
2346
+		// did it all go as planned ?
2347
+		if ($success) {
2348
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2349
+			EE_Error::add_success($msg);
2350
+		} else {
2351
+			$msg = sprintf(
2352
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2353
+				$EVT_ID
2354
+			);
2355
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2356
+			return false;
2357
+		}
2358
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2359
+		return true;
2360
+	}
2361
+
2362
+
2363
+	/**
2364
+	 * get total number of events
2365
+	 *
2366
+	 * @access public
2367
+	 * @return int
2368
+	 * @throws EE_Error
2369
+	 * @throws InvalidArgumentException
2370
+	 * @throws InvalidDataTypeException
2371
+	 * @throws InvalidInterfaceException
2372
+	 */
2373
+	public function total_events()
2374
+	{
2375
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2376
+		return $count;
2377
+	}
2378
+
2379
+
2380
+	/**
2381
+	 * get total number of draft events
2382
+	 *
2383
+	 * @access public
2384
+	 * @return int
2385
+	 * @throws EE_Error
2386
+	 * @throws InvalidArgumentException
2387
+	 * @throws InvalidDataTypeException
2388
+	 * @throws InvalidInterfaceException
2389
+	 */
2390
+	public function total_events_draft()
2391
+	{
2392
+		$where = array(
2393
+			'status' => array('IN', array('draft', 'auto-draft')),
2394
+		);
2395
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2396
+		return $count;
2397
+	}
2398
+
2399
+
2400
+	/**
2401
+	 * get total number of trashed events
2402
+	 *
2403
+	 * @access public
2404
+	 * @return int
2405
+	 * @throws EE_Error
2406
+	 * @throws InvalidArgumentException
2407
+	 * @throws InvalidDataTypeException
2408
+	 * @throws InvalidInterfaceException
2409
+	 */
2410
+	public function total_trashed_events()
2411
+	{
2412
+		$where = array(
2413
+			'status' => 'trash',
2414
+		);
2415
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2416
+		return $count;
2417
+	}
2418
+
2419
+
2420
+	/**
2421
+	 *    _default_event_settings
2422
+	 *    This generates the Default Settings Tab
2423
+	 *
2424
+	 * @return void
2425
+	 * @throws DomainException
2426
+	 * @throws EE_Error
2427
+	 * @throws InvalidArgumentException
2428
+	 * @throws InvalidDataTypeException
2429
+	 * @throws InvalidInterfaceException
2430
+	 */
2431
+	protected function _default_event_settings()
2432
+	{
2433
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2434
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2435
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2436
+		$this->display_admin_page_with_sidebar();
2437
+	}
2438
+
2439
+
2440
+	/**
2441
+	 * Return the form for event settings.
2442
+	 *
2443
+	 * @return EE_Form_Section_Proper
2444
+	 * @throws EE_Error
2445
+	 */
2446
+	protected function _default_event_settings_form()
2447
+	{
2448
+		$registration_config = EE_Registry::instance()->CFG->registration;
2449
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2450
+			// exclude
2451
+			array(
2452
+				EEM_Registration::status_id_cancelled,
2453
+				EEM_Registration::status_id_declined,
2454
+				EEM_Registration::status_id_incomplete,
2455
+				EEM_Registration::status_id_wait_list,
2456
+			),
2457
+			true
2458
+		);
2459
+		return new EE_Form_Section_Proper(
2460
+			array(
2461
+				'name'            => 'update_default_event_settings',
2462
+				'html_id'         => 'update_default_event_settings',
2463
+				'html_class'      => 'form-table',
2464
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2465
+				'subsections'     => apply_filters(
2466
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2467
+					array(
2468
+						'default_reg_status'  => new EE_Select_Input(
2469
+							$registration_stati_for_selection,
2470
+							array(
2471
+								'default'         => isset($registration_config->default_STS_ID)
2472
+													 && array_key_exists(
2473
+														 $registration_config->default_STS_ID,
2474
+														 $registration_stati_for_selection
2475
+													 )
2476
+									? sanitize_text_field($registration_config->default_STS_ID)
2477
+									: EEM_Registration::status_id_pending_payment,
2478
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2479
+													 . EEH_Template::get_help_tab_link(
2480
+														 'default_settings_status_help_tab'
2481
+													 ),
2482
+								'html_help_text'  => esc_html__(
2483
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2484
+									'event_espresso'
2485
+								),
2486
+							)
2487
+						),
2488
+						'default_max_tickets' => new EE_Integer_Input(
2489
+							array(
2490
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2491
+									? $registration_config->default_maximum_number_of_tickets
2492
+									: EEM_Event::get_default_additional_limit(),
2493
+								'html_label_text' => esc_html__(
2494
+									'Default Maximum Tickets Allowed Per Order:',
2495
+									'event_espresso'
2496
+								)
2497
+													 . EEH_Template::get_help_tab_link(
2498
+														 'default_maximum_tickets_help_tab"'
2499
+													 ),
2500
+								'html_help_text'  => esc_html__(
2501
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2502
+									'event_espresso'
2503
+								),
2504
+							)
2505
+						),
2506
+					)
2507
+				),
2508
+			)
2509
+		);
2510
+	}
2511
+
2512
+
2513
+	/**
2514
+	 * @return void
2515
+	 * @throws EE_Error
2516
+	 * @throws InvalidArgumentException
2517
+	 * @throws InvalidDataTypeException
2518
+	 * @throws InvalidInterfaceException
2519
+	 */
2520
+	protected function _update_default_event_settings()
2521
+	{
2522
+		$form = $this->_default_event_settings_form();
2523
+		if ($form->was_submitted()) {
2524
+			$form->receive_form_submission();
2525
+			if ($form->is_valid()) {
2526
+				$registration_config = EE_Registry::instance()->CFG->registration;
2527
+				$valid_data = $form->valid_data();
2528
+				if (isset($valid_data['default_reg_status'])) {
2529
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2530
+				}
2531
+				if (isset($valid_data['default_max_tickets'])) {
2532
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2533
+				}
2534
+				do_action(
2535
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2536
+					$valid_data,
2537
+					EE_Registry::instance()->CFG,
2538
+					$this
2539
+				);
2540
+				// update because data was valid!
2541
+				EE_Registry::instance()->CFG->update_espresso_config();
2542
+				EE_Error::overwrite_success();
2543
+				EE_Error::add_success(
2544
+					__('Default Event Settings were updated', 'event_espresso')
2545
+				);
2546
+			}
2547
+		}
2548
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2549
+	}
2550
+
2551
+
2552
+	/*************        Templates        *************/
2553
+	protected function _template_settings()
2554
+	{
2555
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2556
+		$this->_template_args['preview_img'] = '<img src="'
2557
+											   . EVENTS_ASSETS_URL
2558
+											   . '/images/'
2559
+											   . 'caffeinated_template_features.jpg" alt="'
2560
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2561
+											   . '" />';
2562
+		$this->_template_args['preview_text'] = '<strong>'
2563
+												. esc_html__(
2564
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2565
+													'event_espresso'
2566
+												) . '</strong>';
2567
+		$this->display_admin_caf_preview_page('template_settings_tab');
2568
+	}
2569
+
2570
+
2571
+	/** Event Category Stuff **/
2572
+	/**
2573
+	 * set the _category property with the category object for the loaded page.
2574
+	 *
2575
+	 * @access private
2576
+	 * @return void
2577
+	 */
2578
+	private function _set_category_object()
2579
+	{
2580
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2581
+			return;
2582
+		} //already have the category object so get out.
2583
+		// set default category object
2584
+		$this->_set_empty_category_object();
2585
+		// only set if we've got an id
2586
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2587
+			return;
2588
+		}
2589
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2590
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2591
+		if (! empty($term)) {
2592
+			$this->_category->category_name = $term->name;
2593
+			$this->_category->category_identifier = $term->slug;
2594
+			$this->_category->category_desc = $term->description;
2595
+			$this->_category->id = $term->term_id;
2596
+			$this->_category->parent = $term->parent;
2597
+		}
2598
+	}
2599
+
2600
+
2601
+	/**
2602
+	 * Clears out category properties.
2603
+	 */
2604
+	private function _set_empty_category_object()
2605
+	{
2606
+		$this->_category = new stdClass();
2607
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2608
+		$this->_category->id = $this->_category->parent = 0;
2609
+	}
2610
+
2611
+
2612
+	/**
2613
+	 * @throws DomainException
2614
+	 * @throws EE_Error
2615
+	 * @throws InvalidArgumentException
2616
+	 * @throws InvalidDataTypeException
2617
+	 * @throws InvalidInterfaceException
2618
+	 */
2619
+	protected function _category_list_table()
2620
+	{
2621
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2622
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2623
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2624
+			'add_category',
2625
+			'add_category',
2626
+			array(),
2627
+			'add-new-h2'
2628
+		);
2629
+		$this->display_admin_list_table_page_with_sidebar();
2630
+	}
2631
+
2632
+
2633
+	/**
2634
+	 * Output category details view.
2635
+	 *
2636
+	 * @param string $view
2637
+	 * @throws DomainException
2638
+	 * @throws EE_Error
2639
+	 * @throws InvalidArgumentException
2640
+	 * @throws InvalidDataTypeException
2641
+	 * @throws InvalidInterfaceException
2642
+	 */
2643
+	protected function _category_details($view)
2644
+	{
2645
+		// load formatter helper
2646
+		// load field generator helper
2647
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2648
+		$this->_set_add_edit_form_tags($route);
2649
+		$this->_set_category_object();
2650
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2651
+		$delete_action = 'delete_category';
2652
+		// custom redirect
2653
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2654
+			array('action' => 'category_list'),
2655
+			$this->_admin_base_url
2656
+		);
2657
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2658
+		// take care of contents
2659
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2660
+		$this->display_admin_page_with_sidebar();
2661
+	}
2662
+
2663
+
2664
+	/**
2665
+	 * Output category details content.
2666
+	 *
2667
+	 * @throws DomainException
2668
+	 */
2669
+	protected function _category_details_content()
2670
+	{
2671
+		$editor_args['category_desc'] = array(
2672
+			'type'          => 'wp_editor',
2673
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2674
+			'class'         => 'my_editor_custom',
2675
+			'wpeditor_args' => array('media_buttons' => false),
2676
+		);
2677
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2678
+		$all_terms = get_terms(
2679
+			array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2680
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2681
+		);
2682
+		// setup category select for term parents.
2683
+		$category_select_values[] = array(
2684
+			'text' => esc_html__('No Parent', 'event_espresso'),
2685
+			'id'   => 0,
2686
+		);
2687
+		foreach ($all_terms as $term) {
2688
+			$category_select_values[] = array(
2689
+				'text' => $term->name,
2690
+				'id'   => $term->term_id,
2691
+			);
2692
+		}
2693
+		$category_select = EEH_Form_Fields::select_input(
2694
+			'category_parent',
2695
+			$category_select_values,
2696
+			$this->_category->parent
2697
+		);
2698
+		$template_args = array(
2699
+			'category'                 => $this->_category,
2700
+			'category_select'          => $category_select,
2701
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2702
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2703
+			'disable'                  => '',
2704
+			'disabled_message'         => false,
2705
+		);
2706
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2707
+		return EEH_Template::display_template($template, $template_args, true);
2708
+	}
2709
+
2710
+
2711
+	/**
2712
+	 * Handles deleting categories.
2713
+	 */
2714
+	protected function _delete_categories()
2715
+	{
2716
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2717
+			: (array) $this->_req_data['category_id'];
2718
+		foreach ($cat_ids as $cat_id) {
2719
+			$this->_delete_category($cat_id);
2720
+		}
2721
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2722
+		$query_args = array(
2723
+			'action' => 'category_list',
2724
+		);
2725
+		$this->_redirect_after_action(0, '', '', $query_args);
2726
+	}
2727
+
2728
+
2729
+	/**
2730
+	 * Handles deleting specific category.
2731
+	 *
2732
+	 * @param int $cat_id
2733
+	 */
2734
+	protected function _delete_category($cat_id)
2735
+	{
2736
+		$cat_id = absint($cat_id);
2737
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2738
+	}
2739
+
2740
+
2741
+	/**
2742
+	 * Handles triggering the update or insertion of a new category.
2743
+	 *
2744
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2745
+	 * @throws EE_Error
2746
+	 * @throws InvalidArgumentException
2747
+	 * @throws InvalidDataTypeException
2748
+	 * @throws InvalidInterfaceException
2749
+	 */
2750
+	protected function _insert_or_update_category($new_category)
2751
+	{
2752
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2753
+		$success = 0; // we already have a success message so lets not send another.
2754
+		if ($cat_id) {
2755
+			$query_args = array(
2756
+				'action'     => 'edit_category',
2757
+				'EVT_CAT_ID' => $cat_id,
2758
+			);
2759
+		} else {
2760
+			$query_args = array('action' => 'add_category');
2761
+		}
2762
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2763
+	}
2764
+
2765
+
2766
+	/**
2767
+	 * Inserts or updates category
2768
+	 *
2769
+	 * @param bool $update (true indicates we're updating a category).
2770
+	 * @return bool|mixed|string
2771
+	 */
2772
+	private function _insert_category($update = false)
2773
+	{
2774
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2775
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2776
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2777
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2778
+		if (empty($category_name)) {
2779
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2780
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2781
+			return false;
2782
+		}
2783
+		$term_args = array(
2784
+			'name'        => $category_name,
2785
+			'description' => $category_desc,
2786
+			'parent'      => $category_parent,
2787
+		);
2788
+		// was the category_identifier input disabled?
2789
+		if (isset($this->_req_data['category_identifier'])) {
2790
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2791
+		}
2792
+		$insert_ids = $update
2793
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2794
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2795
+		if (! is_array($insert_ids)) {
2796
+			$msg = esc_html__(
2797
+				'An error occurred and the category has not been saved to the database.',
2798
+				'event_espresso'
2799
+			);
2800
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2801
+		} else {
2802
+			$cat_id = $insert_ids['term_id'];
2803
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2804
+			EE_Error::add_success($msg);
2805
+		}
2806
+		return $cat_id;
2807
+	}
2808
+
2809
+
2810
+	/**
2811
+	 * Gets categories or count of categories matching the arguments in the request.
2812
+	 *
2813
+	 * @param int  $per_page
2814
+	 * @param int  $current_page
2815
+	 * @param bool $count
2816
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2817
+	 * @throws EE_Error
2818
+	 * @throws InvalidArgumentException
2819
+	 * @throws InvalidDataTypeException
2820
+	 * @throws InvalidInterfaceException
2821
+	 */
2822
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2823
+	{
2824
+		// testing term stuff
2825
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2826
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2827
+		$limit = ($current_page - 1) * $per_page;
2828
+		$where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2829
+		if (isset($this->_req_data['s'])) {
2830
+			$sstr = '%' . $this->_req_data['s'] . '%';
2831
+			$where['OR'] = array(
2832
+				'Term.name'   => array('LIKE', $sstr),
2833
+				'description' => array('LIKE', $sstr),
2834
+			);
2835
+		}
2836
+		$query_params = array(
2837
+			$where,
2838
+			'order_by'   => array($orderby => $order),
2839
+			'limit'      => $limit . ',' . $per_page,
2840
+			'force_join' => array('Term'),
2841
+		);
2842
+		$categories = $count
2843
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2844
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2845
+		return $categories;
2846
+	}
2847
+
2848
+	/* end category stuff */
2849
+	/**************/
2850
+
2851
+
2852
+	/**
2853
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2854
+	 *
2855
+	 * @throws EE_Error
2856
+	 * @throws InvalidArgumentException
2857
+	 * @throws InvalidDataTypeException
2858
+	 * @throws InvalidInterfaceException
2859
+	 */
2860
+	public function save_timezonestring_setting()
2861
+	{
2862
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2863
+			? $this->_req_data['timezone_selected']
2864
+			: '';
2865
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2866
+			EE_Error::add_error(
2867
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2868
+				__FILE__,
2869
+				__FUNCTION__,
2870
+				__LINE__
2871
+			);
2872
+			$this->_template_args['error'] = true;
2873
+			$this->_return_json();
2874
+		}
2875
+
2876
+		update_option('timezone_string', $timezone_string);
2877
+		EE_Error::add_success(
2878
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2879
+		);
2880
+		$this->_template_args['success'] = true;
2881
+		$this->_return_json(true, array('action' => 'create_new'));
2882
+	}
2883 2883
 }
Please login to merge, or discard this patch.
Spacing   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -502,9 +502,9 @@  discard block
 block discarded – undo
502 502
         ];
503 503
         // only load EE_Event_Editor_Decaf_Tips if domain is not caffeinated
504 504
         $domain = $this->loader->getShared('EventEspresso\core\domain\Domain');
505
-        if (! $domain->isCaffeinated()) {
505
+        if ( ! $domain->isCaffeinated()) {
506 506
             $this->_page_config['create_new']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
507
-            $this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips' ];
507
+            $this->_page_config['edit']['qtips'] = ['EE_Event_Editor_Decaf_Tips'];
508 508
         }
509 509
     }
510 510
 
@@ -561,13 +561,13 @@  discard block
 block discarded – undo
561 561
     {
562 562
         wp_register_style(
563 563
             'events-admin-css',
564
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
564
+            EVENTS_ASSETS_URL.'events-admin-page.css',
565 565
             [],
566 566
             EVENT_ESPRESSO_VERSION
567 567
         );
568 568
         wp_register_style(
569 569
             'ee-cat-admin',
570
-            EVENTS_ASSETS_URL . 'ee-cat-admin.css',
570
+            EVENTS_ASSETS_URL.'ee-cat-admin.css',
571 571
             [],
572 572
             EVENT_ESPRESSO_VERSION
573 573
         );
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
         // scripts
577 577
         wp_register_script(
578 578
             'event_editor_js',
579
-            EVENTS_ASSETS_URL . 'event_editor.js',
579
+            EVENTS_ASSETS_URL.'event_editor.js',
580 580
             ['ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'],
581 581
             EVENT_ESPRESSO_VERSION,
582 582
             true
@@ -602,16 +602,16 @@  discard block
 block discarded – undo
602 602
         wp_enqueue_style('espresso-ui-theme');
603 603
         wp_register_style(
604 604
             'event-editor-css',
605
-            EVENTS_ASSETS_URL . 'event-editor.css',
605
+            EVENTS_ASSETS_URL.'event-editor.css',
606 606
             ['ee-admin-css'],
607 607
             EVENT_ESPRESSO_VERSION
608 608
         );
609 609
         wp_enqueue_style('event-editor-css');
610 610
         // scripts
611
-        if (! $this->admin_config->useAdvancedEditor()) {
611
+        if ( ! $this->admin_config->useAdvancedEditor()) {
612 612
             wp_register_script(
613 613
                 'event-datetime-metabox',
614
-                EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
614
+                EVENTS_ASSETS_URL.'event-datetime-metabox.js',
615 615
                 ['event_editor_js', 'ee-datepicker'],
616 616
                 EVENT_ESPRESSO_VERSION
617 617
             );
@@ -681,15 +681,15 @@  discard block
 block discarded – undo
681 681
     public function verify_event_edit($event = null, $req_type = '')
682 682
     {
683 683
         // don't need to do this when processing
684
-        if (! empty($req_type)) {
684
+        if ( ! empty($req_type)) {
685 685
             return;
686 686
         }
687 687
         // no event?
688
-        if (! $event instanceof EE_Event) {
688
+        if ( ! $event instanceof EE_Event) {
689 689
             $event = $this->_cpt_model_obj;
690 690
         }
691 691
         // STILL no event?
692
-        if (! $event instanceof EE_Event) {
692
+        if ( ! $event instanceof EE_Event) {
693 693
             return;
694 694
         }
695 695
         $orig_status = $event->status();
@@ -728,7 +728,7 @@  discard block
 block discarded – undo
728 728
             );
729 729
         }
730 730
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
731
-        if (! $event->tickets_on_sale()) {
731
+        if ( ! $event->tickets_on_sale()) {
732 732
             return;
733 733
         }
734 734
         // made it here so show warning
@@ -776,7 +776,7 @@  discard block
 block discarded – undo
776 776
     {
777 777
         $has_timezone_string = get_option('timezone_string');
778 778
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
779
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
779
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
780 780
             EE_Error::add_attention(
781 781
                 sprintf(
782 782
                     __(
@@ -860,31 +860,31 @@  discard block
 block discarded – undo
860 860
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
861 861
         $statuses = array(
862 862
             'sold_out_status'  => array(
863
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
863
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
864 864
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
865 865
             ),
866 866
             'active_status'    => array(
867
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
867
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
868 868
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
869 869
             ),
870 870
             'upcoming_status'  => array(
871
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
871
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
872 872
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
873 873
             ),
874 874
             'postponed_status' => array(
875
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
875
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
876 876
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
877 877
             ),
878 878
             'cancelled_status' => array(
879
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
879
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
880 880
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
881 881
             ),
882 882
             'expired_status'   => array(
883
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
883
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
884 884
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
885 885
             ),
886 886
             'inactive_status'  => array(
887
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
887
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
888 888
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
889 889
             ),
890 890
         );
@@ -903,7 +903,7 @@  discard block
 block discarded – undo
903 903
      */
904 904
     private function _event_model()
905 905
     {
906
-        if (! $this->_event_model instanceof EEM_Event) {
906
+        if ( ! $this->_event_model instanceof EEM_Event) {
907 907
             $this->_event_model = EE_Registry::instance()->load_model('Event');
908 908
         }
909 909
         return $this->_event_model;
@@ -923,7 +923,7 @@  discard block
 block discarded – undo
923 923
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
924 924
     {
925 925
         // make sure this is only when editing
926
-        if (! empty($id)) {
926
+        if ( ! empty($id)) {
927 927
             $post = get_post($id);
928 928
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
929 929
                        . esc_html__('Shortcode', 'event_espresso')
@@ -961,7 +961,7 @@  discard block
 block discarded – undo
961 961
                     'button'
962 962
                 );
963 963
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
964
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
964
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
965 965
             'create_new',
966 966
             'add',
967 967
             array(),
@@ -1121,7 +1121,7 @@  discard block
 block discarded – undo
1121 1121
      */
1122 1122
     protected function _default_venue_update(EE_Event $evtobj, $data)
1123 1123
     {
1124
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1124
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1125 1125
         $venue_model = EE_Registry::instance()->load_model('Venue');
1126 1126
         $rows_affected = null;
1127 1127
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1152,7 +1152,7 @@  discard block
 block discarded – undo
1152 1152
             'status'              => 'publish',
1153 1153
         );
1154 1154
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1155
-        if (! empty($venue_id)) {
1155
+        if ( ! empty($venue_id)) {
1156 1156
             $update_where = array($venue_model->primary_key_name() => $venue_id);
1157 1157
             $rows_affected = $venue_model->update($venue_array, array($update_where));
1158 1158
             // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
@@ -1202,7 +1202,7 @@  discard block
 block discarded – undo
1202 1202
                 'DTT_order'     => $row,
1203 1203
             );
1204 1204
             // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1205
-            if (! empty($dtt['DTT_ID'])) {
1205
+            if ( ! empty($dtt['DTT_ID'])) {
1206 1206
                 $DTM = EE_Registry::instance()
1207 1207
                                   ->load_model('Datetime', array($evtobj->get_timezone()))
1208 1208
                                   ->get_one_by_ID($dtt['DTT_ID']);
@@ -1212,7 +1212,7 @@  discard block
 block discarded – undo
1212 1212
                     $DTM->set($field, $value);
1213 1213
                 }
1214 1214
                 // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1215
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1215
+                $saved_dtts[$DTM->ID()] = $DTM;
1216 1216
             } else {
1217 1217
                 $DTM = EE_Registry::instance()->load_class(
1218 1218
                     'Datetime',
@@ -1245,14 +1245,14 @@  discard block
 block discarded – undo
1245 1245
         foreach ($data['edit_tickets'] as $row => $tkt) {
1246 1246
             $incoming_date_formats = array('Y-m-d', 'h:i a');
1247 1247
             $update_prices = false;
1248
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1249
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1248
+            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1249
+                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1250 1250
             // trim inputs to ensure any excess whitespace is removed.
1251 1251
             $tkt = array_map('trim', $tkt);
1252 1252
             if (empty($tkt['TKT_start_date'])) {
1253 1253
                 // let's use now in the set timezone.
1254 1254
                 $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1255
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1255
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1256 1256
             }
1257 1257
             if (empty($tkt['TKT_end_date'])) {
1258 1258
                 // use the start date of the first datetime
@@ -1287,7 +1287,7 @@  discard block
 block discarded – undo
1287 1287
             // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1288 1288
             // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1289 1289
             // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1290
-            if (! empty($tkt['TKT_ID'])) {
1290
+            if ( ! empty($tkt['TKT_ID'])) {
1291 1291
                 $TKT = EE_Registry::instance()
1292 1292
                                   ->load_model('Ticket', array($evtobj->get_timezone()))
1293 1293
                                   ->get_one_by_ID($tkt['TKT_ID']);
@@ -1327,7 +1327,7 @@  discard block
 block discarded – undo
1327 1327
                         $TKT->set('TKT_deleted', 1);
1328 1328
                         $TKT->save();
1329 1329
                         // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1330
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1330
+                        $saved_tickets[$TKT->ID()] = $TKT;
1331 1331
                         // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1332 1332
                         $TKT = clone $TKT;
1333 1333
                         $TKT->set('TKT_ID', 0);
@@ -1372,9 +1372,9 @@  discard block
 block discarded – undo
1372 1372
             }
1373 1373
             // initially let's add the ticket to the dtt
1374 1374
             $saved_dtt->_add_relation_to($TKT, 'Ticket');
1375
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1375
+            $saved_tickets[$TKT->ID()] = $TKT;
1376 1376
             // add prices to ticket
1377
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1377
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1378 1378
         }
1379 1379
         // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1380 1380
         $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
@@ -1542,7 +1542,7 @@  discard block
 block discarded – undo
1542 1542
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1543 1543
         // load template
1544 1544
         EEH_Template::display_template(
1545
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1545
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1546 1546
             $publish_box_extra_args
1547 1547
         );
1548 1548
     }
@@ -1577,7 +1577,7 @@  discard block
 block discarded – undo
1577 1577
         if ($this->admin_config->useAdvancedEditor()) {
1578 1578
             add_action(
1579 1579
                 'add_meta_boxes_espresso_events',
1580
-                function () {
1580
+                function() {
1581 1581
                     global $current_screen;
1582 1582
                     remove_meta_box('authordiv', $current_screen, 'normal');
1583 1583
                 },
@@ -1653,7 +1653,7 @@  discard block
 block discarded – undo
1653 1653
                     'default_where_conditions' => 'none',
1654 1654
                 )
1655 1655
             );
1656
-            if (! empty($related_tickets)) {
1656
+            if ( ! empty($related_tickets)) {
1657 1657
                 $template_args['total_ticket_rows'] = count($related_tickets);
1658 1658
                 $row = 0;
1659 1659
                 foreach ($related_tickets as $ticket) {
@@ -1687,7 +1687,7 @@  discard block
 block discarded – undo
1687 1687
         );
1688 1688
         $template = apply_filters(
1689 1689
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1690
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1690
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1691 1691
         );
1692 1692
         EEH_Template::display_template($template, $template_args);
1693 1693
     }
@@ -1711,7 +1711,7 @@  discard block
 block discarded – undo
1711 1711
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1712 1712
     {
1713 1713
         $template_args = array(
1714
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1714
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1715 1715
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1716 1716
                 : '',
1717 1717
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1723,10 +1723,10 @@  discard block
 block discarded – undo
1723 1723
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1724 1724
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1725 1725
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1726
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1727
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1726
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1727
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1728 1728
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1729
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1729
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1730 1730
                 : ' disabled=disabled',
1731 1731
         );
1732 1732
         $price = $ticket->ID() !== 0
@@ -1753,7 +1753,7 @@  discard block
 block discarded – undo
1753 1753
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1754 1754
                 )
1755 1755
                 : null;
1756
-            if (! empty($earliest_dtt)) {
1756
+            if ( ! empty($earliest_dtt)) {
1757 1757
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1758 1758
             } else {
1759 1759
                 $template_args['TKT_end_date'] = date(
@@ -1765,7 +1765,7 @@  discard block
 block discarded – undo
1765 1765
         $template_args = array_merge($template_args, $price_args);
1766 1766
         $template = apply_filters(
1767 1767
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1768
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1768
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1769 1769
             $ticket
1770 1770
         );
1771 1771
         return EEH_Template::display_template($template, $template_args, true);
@@ -1820,7 +1820,7 @@  discard block
 block discarded – undo
1820 1820
             $default_reg_status_values
1821 1821
         );
1822 1822
         EEH_Template::display_template(
1823
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1823
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1824 1824
             $template_args
1825 1825
         );
1826 1826
     }
@@ -1850,7 +1850,7 @@  discard block
 block discarded – undo
1850 1850
     {
1851 1851
         $EEME = $this->_event_model();
1852 1852
         $offset = ($current_page - 1) * $per_page;
1853
-        $limit = $count ? null : $offset . ',' . $per_page;
1853
+        $limit = $count ? null : $offset.','.$per_page;
1854 1854
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1855 1855
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1856 1856
         if (isset($this->_req_data['month_range'])) {
@@ -1879,7 +1879,7 @@  discard block
 block discarded – undo
1879 1879
         // categories?
1880 1880
         $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1881 1881
             ? $this->_req_data['EVT_CAT'] : null;
1882
-        if (! empty($category)) {
1882
+        if ( ! empty($category)) {
1883 1883
             $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1884 1884
             $where['Term_Taxonomy.term_id'] = $category;
1885 1885
         }
@@ -1887,7 +1887,7 @@  discard block
 block discarded – undo
1887 1887
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1888 1888
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1889 1889
             $DateTime = new DateTime(
1890
-                $year_r . '-' . $month_r . '-01 00:00:00',
1890
+                $year_r.'-'.$month_r.'-01 00:00:00',
1891 1891
                 new DateTimeZone('UTC')
1892 1892
             );
1893 1893
             $start = $DateTime->getTimestamp();
@@ -1913,9 +1913,9 @@  discard block
 block discarded – undo
1913 1913
                             ->format(implode(' ', $start_formats));
1914 1914
             $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1915 1915
         }
1916
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1916
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1917 1917
             $where['EVT_wp_user'] = get_current_user_id();
1918
-        } elseif (! isset($where['status'])
1918
+        } elseif ( ! isset($where['status'])
1919 1919
             && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1920 1920
         ) {
1921 1921
             $where['OR'] = array(
@@ -1935,7 +1935,7 @@  discard block
 block discarded – undo
1935 1935
         }
1936 1936
         // search query handling
1937 1937
         if (isset($this->_req_data['s'])) {
1938
-            $search_string = '%' . $this->_req_data['s'] . '%';
1938
+            $search_string = '%'.$this->_req_data['s'].'%';
1939 1939
             $where['OR'] = array(
1940 1940
                 'EVT_name'       => array('LIKE', $search_string),
1941 1941
                 'EVT_desc'       => array('LIKE', $search_string),
@@ -2050,7 +2050,7 @@  discard block
 block discarded – undo
2050 2050
             // clean status
2051 2051
             $event_status = sanitize_key($event_status);
2052 2052
             // grab status
2053
-            if (! empty($event_status)) {
2053
+            if ( ! empty($event_status)) {
2054 2054
                 $success = $this->_change_event_status($EVT_ID, $event_status);
2055 2055
             } else {
2056 2056
                 $success = false;
@@ -2092,7 +2092,7 @@  discard block
 block discarded – undo
2092 2092
         // clean status
2093 2093
         $event_status = sanitize_key($event_status);
2094 2094
         // grab status
2095
-        if (! empty($event_status)) {
2095
+        if ( ! empty($event_status)) {
2096 2096
             $success = true;
2097 2097
             // determine the event id and set to array.
2098 2098
             $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
@@ -2144,7 +2144,7 @@  discard block
 block discarded – undo
2144 2144
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2145 2145
     {
2146 2146
         // grab event id
2147
-        if (! $EVT_ID) {
2147
+        if ( ! $EVT_ID) {
2148 2148
             $msg = esc_html__(
2149 2149
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2150 2150
                 'event_espresso'
@@ -2215,8 +2215,8 @@  discard block
 block discarded – undo
2215 2215
             // get list of events with no prices
2216 2216
             $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2217 2217
             // remove this event from the list of events with no prices
2218
-            if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2219
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2218
+            if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2219
+                unset($espresso_no_ticket_prices[$EVT_ID]);
2220 2220
             }
2221 2221
             update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2222 2222
         } else {
@@ -2263,7 +2263,7 @@  discard block
 block discarded – undo
2263 2263
                 $results = $this->_permanently_delete_event($EVT_ID);
2264 2264
                 $success = $results !== false ? $success : false;
2265 2265
                 // remove this event from the list of events with no prices
2266
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2266
+                unset($espresso_no_ticket_prices[$EVT_ID]);
2267 2267
             } else {
2268 2268
                 $success = false;
2269 2269
                 $msg = esc_html__(
@@ -2295,7 +2295,7 @@  discard block
 block discarded – undo
2295 2295
     private function _permanently_delete_event($EVT_ID = 0)
2296 2296
     {
2297 2297
         // grab event id
2298
-        if (! $EVT_ID) {
2298
+        if ( ! $EVT_ID) {
2299 2299
             $msg = esc_html__(
2300 2300
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2301 2301
                 'event_espresso'
@@ -2303,12 +2303,12 @@  discard block
 block discarded – undo
2303 2303
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2304 2304
             return false;
2305 2305
         }
2306
-        if (! $this->_cpt_model_obj instanceof EE_Event
2306
+        if ( ! $this->_cpt_model_obj instanceof EE_Event
2307 2307
             || $this->_cpt_model_obj->ID() !== $EVT_ID
2308 2308
         ) {
2309 2309
             $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2310 2310
         }
2311
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2311
+        if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2312 2312
             return false;
2313 2313
         }
2314 2314
         // need to delete related tickets and prices first.
@@ -2330,7 +2330,7 @@  discard block
 block discarded – undo
2330 2330
         }
2331 2331
         // any attached question groups?
2332 2332
         $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2333
-        if (! empty($question_groups)) {
2333
+        if ( ! empty($question_groups)) {
2334 2334
             foreach ($question_groups as $question_group) {
2335 2335
                 $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2336 2336
             }
@@ -2563,7 +2563,7 @@  discard block
 block discarded – undo
2563 2563
                                                 . esc_html__(
2564 2564
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2565 2565
                                                     'event_espresso'
2566
-                                                ) . '</strong>';
2566
+                                                ).'</strong>';
2567 2567
         $this->display_admin_caf_preview_page('template_settings_tab');
2568 2568
     }
2569 2569
 
@@ -2583,12 +2583,12 @@  discard block
 block discarded – undo
2583 2583
         // set default category object
2584 2584
         $this->_set_empty_category_object();
2585 2585
         // only set if we've got an id
2586
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2586
+        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2587 2587
             return;
2588 2588
         }
2589 2589
         $category_id = absint($this->_req_data['EVT_CAT_ID']);
2590 2590
         $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2591
-        if (! empty($term)) {
2591
+        if ( ! empty($term)) {
2592 2592
             $this->_category->category_name = $term->name;
2593 2593
             $this->_category->category_identifier = $term->slug;
2594 2594
             $this->_category->category_desc = $term->description;
@@ -2620,7 +2620,7 @@  discard block
 block discarded – undo
2620 2620
     {
2621 2621
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2622 2622
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2623
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2623
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2624 2624
             'add_category',
2625 2625
             'add_category',
2626 2626
             array(),
@@ -2703,7 +2703,7 @@  discard block
 block discarded – undo
2703 2703
             'disable'                  => '',
2704 2704
             'disabled_message'         => false,
2705 2705
         );
2706
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2706
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2707 2707
         return EEH_Template::display_template($template, $template_args, true);
2708 2708
     }
2709 2709
 
@@ -2792,7 +2792,7 @@  discard block
 block discarded – undo
2792 2792
         $insert_ids = $update
2793 2793
             ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2794 2794
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2795
-        if (! is_array($insert_ids)) {
2795
+        if ( ! is_array($insert_ids)) {
2796 2796
             $msg = esc_html__(
2797 2797
                 'An error occurred and the category has not been saved to the database.',
2798 2798
                 'event_espresso'
@@ -2827,7 +2827,7 @@  discard block
 block discarded – undo
2827 2827
         $limit = ($current_page - 1) * $per_page;
2828 2828
         $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2829 2829
         if (isset($this->_req_data['s'])) {
2830
-            $sstr = '%' . $this->_req_data['s'] . '%';
2830
+            $sstr = '%'.$this->_req_data['s'].'%';
2831 2831
             $where['OR'] = array(
2832 2832
                 'Term.name'   => array('LIKE', $sstr),
2833 2833
                 'description' => array('LIKE', $sstr),
@@ -2836,7 +2836,7 @@  discard block
 block discarded – undo
2836 2836
         $query_params = array(
2837 2837
             $where,
2838 2838
             'order_by'   => array($orderby => $order),
2839
-            'limit'      => $limit . ',' . $per_page,
2839
+            'limit'      => $limit.','.$per_page,
2840 2840
             'force_join' => array('Term'),
2841 2841
         );
2842 2842
         $categories = $count
Please login to merge, or discard this patch.
core/admin/EE_Admin_Page.core.php 1 patch
Indentation   +4040 added lines, -4040 removed lines patch added patch discarded remove patch
@@ -18,4109 +18,4109 @@
 block discarded – undo
18 18
  */
19 19
 abstract class EE_Admin_Page extends EE_Base implements InterminableInterface
20 20
 {
21
-    /**
22
-     * @var EE_Admin_Config
23
-     */
24
-    protected $admin_config;
21
+	/**
22
+	 * @var EE_Admin_Config
23
+	 */
24
+	protected $admin_config;
25 25
 
26
-    /**
27
-     * @var LoaderInterface $loader
28
-     */
29
-    protected $loader;
26
+	/**
27
+	 * @var LoaderInterface $loader
28
+	 */
29
+	protected $loader;
30 30
 
31
-    // set in _init_page_props()
32
-    public $page_slug;
31
+	// set in _init_page_props()
32
+	public $page_slug;
33 33
 
34
-    public $page_label;
34
+	public $page_label;
35 35
 
36
-    public $page_folder;
36
+	public $page_folder;
37 37
 
38
-    // set in define_page_props()
39
-    protected $_admin_base_url;
38
+	// set in define_page_props()
39
+	protected $_admin_base_url;
40 40
 
41
-    protected $_admin_base_path;
41
+	protected $_admin_base_path;
42 42
 
43
-    protected $_admin_page_title;
43
+	protected $_admin_page_title;
44 44
 
45
-    protected $_labels;
45
+	protected $_labels;
46 46
 
47 47
 
48
-    // set early within EE_Admin_Init
49
-    protected $_wp_page_slug;
48
+	// set early within EE_Admin_Init
49
+	protected $_wp_page_slug;
50 50
 
51
-    // nav tabs
52
-    protected $_nav_tabs;
51
+	// nav tabs
52
+	protected $_nav_tabs;
53 53
 
54
-    protected $_default_nav_tab_name;
54
+	protected $_default_nav_tab_name;
55 55
 
56
-    /**
57
-     * @var array $_help_tour
58
-     */
59
-    protected $_help_tour = array();
56
+	/**
57
+	 * @var array $_help_tour
58
+	 */
59
+	protected $_help_tour = array();
60 60
 
61 61
 
62
-    // template variables (used by templates)
63
-    protected $_template_path;
62
+	// template variables (used by templates)
63
+	protected $_template_path;
64 64
 
65
-    protected $_column_template_path;
65
+	protected $_column_template_path;
66 66
 
67
-    /**
68
-     * @var array $_template_args
69
-     */
70
-    protected $_template_args = array();
67
+	/**
68
+	 * @var array $_template_args
69
+	 */
70
+	protected $_template_args = array();
71 71
 
72
-    /**
73
-     * this will hold the list table object for a given view.
74
-     *
75
-     * @var EE_Admin_List_Table $_list_table_object
76
-     */
77
-    protected $_list_table_object;
72
+	/**
73
+	 * this will hold the list table object for a given view.
74
+	 *
75
+	 * @var EE_Admin_List_Table $_list_table_object
76
+	 */
77
+	protected $_list_table_object;
78 78
 
79
-    // boolean
80
-    protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
79
+	// boolean
80
+	protected $_is_UI_request; // this starts at null so we can have no header routes progress through two states.
81 81
 
82
-    protected $_routing;
82
+	protected $_routing;
83 83
 
84
-    // list table args
85
-    protected $_view;
84
+	// list table args
85
+	protected $_view;
86 86
 
87
-    protected $_views;
87
+	protected $_views;
88 88
 
89 89
 
90
-    // action => method pairs used for routing incoming requests
91
-    protected $_page_routes;
90
+	// action => method pairs used for routing incoming requests
91
+	protected $_page_routes;
92 92
 
93
-    /**
94
-     * @var array $_page_config
95
-     */
96
-    protected $_page_config;
93
+	/**
94
+	 * @var array $_page_config
95
+	 */
96
+	protected $_page_config;
97 97
 
98
-    /**
99
-     * the current page route and route config
100
-     *
101
-     * @var string $_route
102
-     */
103
-    protected $_route;
98
+	/**
99
+	 * the current page route and route config
100
+	 *
101
+	 * @var string $_route
102
+	 */
103
+	protected $_route;
104 104
 
105
-    /**
106
-     * @var string $_cpt_route
107
-     */
108
-    protected $_cpt_route;
105
+	/**
106
+	 * @var string $_cpt_route
107
+	 */
108
+	protected $_cpt_route;
109 109
 
110
-    /**
111
-     * @var array $_route_config
112
-     */
113
-    protected $_route_config;
110
+	/**
111
+	 * @var array $_route_config
112
+	 */
113
+	protected $_route_config;
114 114
 
115
-    /**
116
-     * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
117
-     * actions.
118
-     *
119
-     * @since 4.6.x
120
-     * @var array.
121
-     */
122
-    protected $_default_route_query_args;
123
-
124
-    // set via request page and action args.
125
-    protected $_current_page;
126
-
127
-    protected $_current_view;
128
-
129
-    protected $_current_page_view_url;
130
-
131
-    // sanitized request action (and nonce)
132
-
133
-    /**
134
-     * @var string $_req_action
135
-     */
136
-    protected $_req_action;
137
-
138
-    /**
139
-     * @var string $_req_nonce
140
-     */
141
-    protected $_req_nonce;
142
-
143
-    // search related
144
-    protected $_search_btn_label;
145
-
146
-    protected $_search_box_callback;
147
-
148
-    /**
149
-     * WP Current Screen object
150
-     *
151
-     * @var WP_Screen
152
-     */
153
-    protected $_current_screen;
154
-
155
-    // for holding EE_Admin_Hooks object when needed (set via set_hook_object())
156
-    protected $_hook_obj;
157
-
158
-    // for holding incoming request data
159
-    protected $_req_data;
160
-
161
-    // yes / no array for admin form fields
162
-    protected $_yes_no_values = array();
163
-
164
-    // some default things shared by all child classes
165
-    protected $_default_espresso_metaboxes;
166
-
167
-    /**
168
-     *    EE_Registry Object
169
-     *
170
-     * @var    EE_Registry
171
-     */
172
-    protected $EE;
173
-
174
-
175
-    /**
176
-     * This is just a property that flags whether the given route is a caffeinated route or not.
177
-     *
178
-     * @var boolean
179
-     */
180
-    protected $_is_caf = false;
181
-
182
-
183
-    /**
184
-     * @Constructor
185
-     * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
186
-     * @throws InvalidArgumentException
187
-     * @throws InvalidDataTypeException
188
-     * @throws InvalidInterfaceException
189
-     * @throws ReflectionException
190
-     */
191
-    public function __construct($routing = true)
192
-    {
193
-        $this->loader = LoaderFactory::getLoader();
194
-        $this->admin_config = $this->loader->getShared('EE_Admin_Config');
195
-        if (strpos($this->_get_dir(), 'caffeinated') !== false) {
196
-            $this->_is_caf = true;
197
-        }
198
-        $this->_yes_no_values = array(
199
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
200
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
201
-        );
202
-        // set the _req_data property.
203
-        $this->_req_data = array_merge($_GET, $_POST);
204
-        // routing enabled?
205
-        $this->_routing = $routing;
206
-    }
207
-
208
-
209
-    /**
210
-     * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
211
-     * for child classes that needed to set properties prior to these methods getting called,
212
-     * but also needed the parent class to have its construction completed as well.
213
-     * Bottom line is that constructors should ONLY be used for setting initial properties
214
-     * and any complex initialization logic should only run after instantiation is complete.
215
-     *
216
-     * This method gets called immediately after construction from within
217
-     *      EE_Admin_Page_Init::_initialize_admin_page()
218
-     *
219
-     * @throws EE_Error
220
-     * @throws InvalidArgumentException
221
-     * @throws InvalidDataTypeException
222
-     * @throws InvalidInterfaceException
223
-     * @throws ReflectionException
224
-     * @since $VID:$
225
-     */
226
-    public function initializePage()
227
-    {
228
-        // set initial page props (child method)
229
-        $this->_init_page_props();
230
-        // set global defaults
231
-        $this->_set_defaults();
232
-        // set early because incoming requests could be ajax related and we need to register those hooks.
233
-        $this->_global_ajax_hooks();
234
-        $this->_ajax_hooks();
235
-        // other_page_hooks have to be early too.
236
-        $this->_do_other_page_hooks();
237
-        // This just allows us to have extending classes do something specific
238
-        // before the parent constructor runs _page_setup().
239
-        if (method_exists($this, '_before_page_setup')) {
240
-            $this->_before_page_setup();
241
-        }
242
-        // set up page dependencies
243
-        $this->_page_setup();
244
-    }
245
-
246
-
247
-    /**
248
-     * _init_page_props
249
-     * Child classes use to set at least the following properties:
250
-     * $page_slug.
251
-     * $page_label.
252
-     *
253
-     * @abstract
254
-     * @return void
255
-     */
256
-    abstract protected function _init_page_props();
257
-
258
-
259
-    /**
260
-     * _ajax_hooks
261
-     * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
262
-     * Note: within the ajax callback methods.
263
-     *
264
-     * @abstract
265
-     * @return void
266
-     */
267
-    abstract protected function _ajax_hooks();
268
-
269
-
270
-    /**
271
-     * _define_page_props
272
-     * child classes define page properties in here.  Must include at least:
273
-     * $_admin_base_url = base_url for all admin pages
274
-     * $_admin_page_title = default admin_page_title for admin pages
275
-     * $_labels = array of default labels for various automatically generated elements:
276
-     *    array(
277
-     *        'buttons' => array(
278
-     *            'add' => esc_html__('label for add new button'),
279
-     *            'edit' => esc_html__('label for edit button'),
280
-     *            'delete' => esc_html__('label for delete button')
281
-     *            )
282
-     *        )
283
-     *
284
-     * @abstract
285
-     * @return void
286
-     */
287
-    abstract protected function _define_page_props();
288
-
289
-
290
-    /**
291
-     * _set_page_routes
292
-     * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
293
-     * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
294
-     * have a 'default' route. Here's the format
295
-     * $this->_page_routes = array(
296
-     *        'default' => array(
297
-     *            'func' => '_default_method_handling_route',
298
-     *            'args' => array('array','of','args'),
299
-     *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
300
-     *            ajax request, backend processing)
301
-     *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
302
-     *            headers route after.  The string you enter here should match the defined route reference for a
303
-     *            headers sent route.
304
-     *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
305
-     *            this route.
306
-     *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
307
-     *            checks).
308
-     *        ),
309
-     *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
310
-     *        handling method.
311
-     *        )
312
-     * )
313
-     *
314
-     * @abstract
315
-     * @return void
316
-     */
317
-    abstract protected function _set_page_routes();
318
-
319
-
320
-    /**
321
-     * _set_page_config
322
-     * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
323
-     * array corresponds to the page_route for the loaded page. Format:
324
-     * $this->_page_config = array(
325
-     *        'default' => array(
326
-     *            'labels' => array(
327
-     *                'buttons' => array(
328
-     *                    'add' => esc_html__('label for adding item'),
329
-     *                    'edit' => esc_html__('label for editing item'),
330
-     *                    'delete' => esc_html__('label for deleting item')
331
-     *                ),
332
-     *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
333
-     *            ), //optional an array of custom labels for various automatically generated elements to use on the
334
-     *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
335
-     *            _define_page_props() method
336
-     *            'nav' => array(
337
-     *                'label' => esc_html__('Label for Tab', 'event_espresso').
338
-     *                'url' => 'http://someurl', //automatically generated UNLESS you define
339
-     *                'css_class' => 'css-class', //automatically generated UNLESS you define
340
-     *                'order' => 10, //required to indicate tab position.
341
-     *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
342
-     *                displayed then add this parameter.
343
-     *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
344
-     *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
345
-     *            metaboxes set for eventespresso admin pages.
346
-     *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
347
-     *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
348
-     *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
349
-     *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
350
-     *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
351
-     *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
352
-     *            array indicates the max number of columns (4) and the default number of columns on page load (2).
353
-     *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
354
-     *            want to display.
355
-     *            'help_tabs' => array( //this is used for adding help tabs to a page
356
-     *                'tab_id' => array(
357
-     *                    'title' => 'tab_title',
358
-     *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
359
-     *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
360
-     *                    should match a file in the admin folder's "help_tabs" dir (ie..
361
-     *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
362
-     *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
363
-     *                    attempt to use the callback which should match the name of a method in the class
364
-     *                    ),
365
-     *                'tab2_id' => array(
366
-     *                    'title' => 'tab2 title',
367
-     *                    'filename' => 'file_name_2'
368
-     *                    'callback' => 'callback_method_for_content',
369
-     *                 ),
370
-     *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
371
-     *            help tab area on an admin page. @link
372
-     *            http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
373
-     *            'help_tour' => array(
374
-     *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located
375
-     *                in a folder for this admin page named "help_tours", a file name matching the key given here
376
-     *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
377
-     *            ),
378
-     *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is
379
-     *            true if it isn't present).  To remove the requirement for a nonce check when this route is visited
380
-     *            just set
381
-     *            'require_nonce' to FALSE
382
-     *            )
383
-     * )
384
-     *
385
-     * @abstract
386
-     * @return void
387
-     */
388
-    abstract protected function _set_page_config();
389
-
390
-
391
-
392
-
393
-
394
-    /** end sample help_tour methods **/
395
-    /**
396
-     * _add_screen_options
397
-     * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
398
-     * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
399
-     * to a particular view.
400
-     *
401
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
402
-     *         see also WP_Screen object documents...
403
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
404
-     * @abstract
405
-     * @return void
406
-     */
407
-    abstract protected function _add_screen_options();
408
-
409
-
410
-    /**
411
-     * _add_feature_pointers
412
-     * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
413
-     * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
414
-     * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
415
-     * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
416
-     * extended) also see:
417
-     *
418
-     * @link   http://eamann.com/tech/wordpress-portland/
419
-     * @abstract
420
-     * @return void
421
-     */
422
-    abstract protected function _add_feature_pointers();
423
-
424
-
425
-    /**
426
-     * load_scripts_styles
427
-     * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
428
-     * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
429
-     * scripts/styles per view by putting them in a dynamic function in this format
430
-     * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
431
-     *
432
-     * @abstract
433
-     * @return void
434
-     */
435
-    abstract public function load_scripts_styles();
436
-
437
-
438
-    /**
439
-     * admin_init
440
-     * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
441
-     * all pages/views loaded by child class.
442
-     *
443
-     * @abstract
444
-     * @return void
445
-     */
446
-    abstract public function admin_init();
447
-
448
-
449
-    /**
450
-     * admin_notices
451
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
452
-     * all pages/views loaded by child class.
453
-     *
454
-     * @abstract
455
-     * @return void
456
-     */
457
-    abstract public function admin_notices();
458
-
459
-
460
-    /**
461
-     * admin_footer_scripts
462
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
463
-     * will apply to all pages/views loaded by child class.
464
-     *
465
-     * @return void
466
-     */
467
-    abstract public function admin_footer_scripts();
468
-
469
-
470
-    /**
471
-     * admin_footer
472
-     * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
473
-     * apply to all pages/views loaded by child class.
474
-     *
475
-     * @return void
476
-     */
477
-    public function admin_footer()
478
-    {
479
-    }
480
-
481
-
482
-    /**
483
-     * _global_ajax_hooks
484
-     * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
485
-     * Note: within the ajax callback methods.
486
-     *
487
-     * @abstract
488
-     * @return void
489
-     */
490
-    protected function _global_ajax_hooks()
491
-    {
492
-        // for lazy loading of metabox content
493
-        add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
494
-    }
495
-
496
-
497
-    public function ajax_metabox_content()
498
-    {
499
-        $contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
500
-        $url = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
501
-        EE_Admin_Page::cached_rss_display($contentid, $url);
502
-        wp_die();
503
-    }
504
-
505
-
506
-    /**
507
-     * _page_setup
508
-     * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested
509
-     * doesn't match the object.
510
-     *
511
-     * @final
512
-     * @return void
513
-     * @throws EE_Error
514
-     * @throws InvalidArgumentException
515
-     * @throws ReflectionException
516
-     * @throws InvalidDataTypeException
517
-     * @throws InvalidInterfaceException
518
-     */
519
-    final protected function _page_setup()
520
-    {
521
-        // requires?
522
-        // admin_init stuff - global - we're setting this REALLY early
523
-        // so if EE_Admin pages have to hook into other WP pages they can.
524
-        // But keep in mind, not everything is available from the EE_Admin Page object at this point.
525
-        add_action('admin_init', array($this, 'admin_init_global'), 5);
526
-        // next verify if we need to load anything...
527
-        $this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
528
-        $this->page_folder = strtolower(
529
-            str_replace(array('_Admin_Page', 'Extend_'), '', get_class($this))
530
-        );
531
-        global $ee_menu_slugs;
532
-        $ee_menu_slugs = (array) $ee_menu_slugs;
533
-        if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))) {
534
-            return;
535
-        }
536
-        // becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
537
-        if (isset($this->_req_data['action2']) && $this->_req_data['action'] === '-1') {
538
-            $this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] !== '-1'
539
-                ? $this->_req_data['action2']
540
-                : $this->_req_data['action'];
541
-        }
542
-        // then set blank or -1 action values to 'default'
543
-        $this->_req_action = isset($this->_req_data['action'])
544
-                             && ! empty($this->_req_data['action'])
545
-                             && $this->_req_data['action'] !== '-1'
546
-            ? sanitize_key($this->_req_data['action'])
547
-            : 'default';
548
-        // if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.
549
-        //  This covers cases where we're coming in from a list table that isn't on the default route.
550
-        $this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route'])
551
-            ? $this->_req_data['route'] : $this->_req_action;
552
-        // however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
553
-        $this->_req_action = defined('DOING_AJAX') && isset($this->_req_data['route'])
554
-            ? $this->_req_data['route']
555
-            : $this->_req_action;
556
-        $this->_current_view = $this->_req_action;
557
-        $this->_req_nonce = $this->_req_action . '_nonce';
558
-        $this->_define_page_props();
559
-        $this->_current_page_view_url = add_query_arg(
560
-            array('page' => $this->_current_page, 'action' => $this->_current_view),
561
-            $this->_admin_base_url
562
-        );
563
-        // default things
564
-        $this->_default_espresso_metaboxes = array(
565
-            '_espresso_news_post_box',
566
-            '_espresso_links_post_box',
567
-            '_espresso_ratings_request',
568
-            '_espresso_sponsors_post_box',
569
-        );
570
-        // set page configs
571
-        $this->_set_page_routes();
572
-        $this->_set_page_config();
573
-        // let's include any referrer data in our default_query_args for this route for "stickiness".
574
-        if (isset($this->_req_data['wp_referer'])) {
575
-            $this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
576
-        }
577
-        // for caffeinated and other extended functionality.
578
-        //  If there is a _extend_page_config method
579
-        // then let's run that to modify the all the various page configuration arrays
580
-        if (method_exists($this, '_extend_page_config')) {
581
-            $this->_extend_page_config();
582
-        }
583
-        // for CPT and other extended functionality.
584
-        // If there is an _extend_page_config_for_cpt
585
-        // then let's run that to modify all the various page configuration arrays.
586
-        if (method_exists($this, '_extend_page_config_for_cpt')) {
587
-            $this->_extend_page_config_for_cpt();
588
-        }
589
-        // filter routes and page_config so addons can add their stuff. Filtering done per class
590
-        $this->_page_routes = apply_filters(
591
-            'FHEE__' . get_class($this) . '__page_setup__page_routes',
592
-            $this->_page_routes,
593
-            $this
594
-        );
595
-        $this->_page_config = apply_filters(
596
-            'FHEE__' . get_class($this) . '__page_setup__page_config',
597
-            $this->_page_config,
598
-            $this
599
-        );
600
-        // if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
601
-        // then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
602
-        if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
603
-            add_action(
604
-                'AHEE__EE_Admin_Page__route_admin_request',
605
-                array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
606
-                10,
607
-                2
608
-            );
609
-        }
610
-        // next route only if routing enabled
611
-        if ($this->_routing && ! defined('DOING_AJAX')) {
612
-            $this->_verify_routes();
613
-            // next let's just check user_access and kill if no access
614
-            $this->check_user_access();
615
-            if ($this->_is_UI_request) {
616
-                // admin_init stuff - global, all views for this page class, specific view
617
-                add_action('admin_init', array($this, 'admin_init'), 10);
618
-                if (method_exists($this, 'admin_init_' . $this->_current_view)) {
619
-                    add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
620
-                }
621
-            } else {
622
-                // hijack regular WP loading and route admin request immediately
623
-                @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
624
-                $this->route_admin_request();
625
-            }
626
-        }
627
-    }
628
-
629
-
630
-    /**
631
-     * Provides a way for related child admin pages to load stuff on the loaded admin page.
632
-     *
633
-     * @return void
634
-     * @throws EE_Error
635
-     */
636
-    private function _do_other_page_hooks()
637
-    {
638
-        $registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
639
-        foreach ($registered_pages as $page) {
640
-            // now let's setup the file name and class that should be present
641
-            $classname = str_replace('.class.php', '', $page);
642
-            // autoloaders should take care of loading file
643
-            if (! class_exists($classname)) {
644
-                $error_msg[] = sprintf(
645
-                    esc_html__(
646
-                        'Something went wrong with loading the %s admin hooks page.',
647
-                        'event_espresso'
648
-                    ),
649
-                    $page
650
-                );
651
-                $error_msg[] = $error_msg[0]
652
-                               . "\r\n"
653
-                               . sprintf(
654
-                                   esc_html__(
655
-                                       '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',
656
-                                       'event_espresso'
657
-                                   ),
658
-                                   $page,
659
-                                   '<br />',
660
-                                   '<strong>' . $classname . '</strong>'
661
-                               );
662
-                throw new EE_Error(implode('||', $error_msg));
663
-            }
664
-            // // notice we are passing the instance of this class to the hook object.
665
-            $this->loader->getShared($classname, [$this]);
666
-        }
667
-    }
668
-
669
-
670
-    /**
671
-     * @throws DomainException
672
-     * @throws EE_Error
673
-     * @throws InvalidArgumentException
674
-     * @throws InvalidDataTypeException
675
-     * @throws InvalidInterfaceException
676
-     * @throws ReflectionException
677
-     * @since $VID:$
678
-     */
679
-    public function load_page_dependencies()
680
-    {
681
-        try {
682
-            $this->_load_page_dependencies();
683
-        } catch (EE_Error $e) {
684
-            $e->get_error();
685
-        }
686
-    }
687
-
688
-
689
-    /**
690
-     * load_page_dependencies
691
-     * loads things specific to this page class when its loaded.  Really helps with efficiency.
692
-     *
693
-     * @return void
694
-     * @throws DomainException
695
-     * @throws EE_Error
696
-     * @throws InvalidArgumentException
697
-     * @throws InvalidDataTypeException
698
-     * @throws InvalidInterfaceException
699
-     * @throws ReflectionException
700
-     */
701
-    protected function _load_page_dependencies()
702
-    {
703
-        // let's set the current_screen and screen options to override what WP set
704
-        $this->_current_screen = get_current_screen();
705
-        // load admin_notices - global, page class, and view specific
706
-        add_action('admin_notices', array($this, 'admin_notices_global'), 5);
707
-        add_action('admin_notices', array($this, 'admin_notices'), 10);
708
-        if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
709
-            add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
710
-        }
711
-        // load network admin_notices - global, page class, and view specific
712
-        add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
713
-        if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
714
-            add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
715
-        }
716
-        // this will save any per_page screen options if they are present
717
-        $this->_set_per_page_screen_options();
718
-        // setup list table properties
719
-        $this->_set_list_table();
720
-        // child classes can "register" a metabox to be automatically handled via the _page_config array property.
721
-        // However in some cases the metaboxes will need to be added within a route handling callback.
722
-        $this->_add_registered_meta_boxes();
723
-        $this->_add_screen_columns();
724
-        // add screen options - global, page child class, and view specific
725
-        $this->_add_global_screen_options();
726
-        $this->_add_screen_options();
727
-        $add_screen_options = "_add_screen_options_{$this->_current_view}";
728
-        if (method_exists($this, $add_screen_options)) {
729
-            $this->{$add_screen_options}();
730
-        }
731
-        // add help tab(s) and tours- set via page_config and qtips.
732
-        $this->_add_help_tour();
733
-        $this->_add_help_tabs();
734
-        $this->_add_qtips();
735
-        // add feature_pointers - global, page child class, and view specific
736
-        $this->_add_feature_pointers();
737
-        $this->_add_global_feature_pointers();
738
-        $add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
739
-        if (method_exists($this, $add_feature_pointer)) {
740
-            $this->{$add_feature_pointer}();
741
-        }
742
-        // enqueue scripts/styles - global, page class, and view specific
743
-        add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
744
-        add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
745
-        if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
746
-            add_action('admin_enqueue_scripts', array($this, "load_scripts_styles_{$this->_current_view}"), 15);
747
-        }
748
-        add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
749
-        // admin_print_footer_scripts - global, page child class, and view specific.
750
-        // NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
751
-        // In most cases that's doing_it_wrong().  But adding hidden container elements etc.
752
-        // is a good use case. Notice the late priority we're giving these
753
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
754
-        add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
755
-        if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
756
-            add_action('admin_print_footer_scripts', array($this, "admin_footer_scripts_{$this->_current_view}"), 101);
757
-        }
758
-        // admin footer scripts
759
-        add_action('admin_footer', array($this, 'admin_footer_global'), 99);
760
-        add_action('admin_footer', array($this, 'admin_footer'), 100);
761
-        if (method_exists($this, "admin_footer_{$this->_current_view}")) {
762
-            add_action('admin_footer', array($this, "admin_footer_{$this->_current_view}"), 101);
763
-        }
764
-        do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
765
-        // targeted hook
766
-        do_action(
767
-            "FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
768
-        );
769
-    }
770
-
771
-
772
-    /**
773
-     * _set_defaults
774
-     * This sets some global defaults for class properties.
775
-     */
776
-    private function _set_defaults()
777
-    {
778
-        $this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
779
-        $this->_event = $this->_template_path = $this->_column_template_path = null;
780
-        $this->_nav_tabs = $this->_views = $this->_page_routes = array();
781
-        $this->_page_config = $this->_default_route_query_args = array();
782
-        $this->_default_nav_tab_name = 'overview';
783
-        // init template args
784
-        $this->_template_args = array(
785
-            'admin_page_header'  => '',
786
-            'admin_page_content' => '',
787
-            'post_body_content'  => '',
788
-            'before_list_table'  => '',
789
-            'after_list_table'   => '',
790
-        );
791
-    }
792
-
793
-
794
-    /**
795
-     * route_admin_request
796
-     *
797
-     * @see    _route_admin_request()
798
-     * @return exception|void error
799
-     * @throws InvalidArgumentException
800
-     * @throws InvalidInterfaceException
801
-     * @throws InvalidDataTypeException
802
-     * @throws EE_Error
803
-     * @throws ReflectionException
804
-     */
805
-    public function route_admin_request()
806
-    {
807
-        try {
808
-            $this->_route_admin_request();
809
-        } catch (EE_Error $e) {
810
-            $e->get_error();
811
-        }
812
-    }
813
-
814
-
815
-    public function set_wp_page_slug($wp_page_slug)
816
-    {
817
-        $this->_wp_page_slug = $wp_page_slug;
818
-        // if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
819
-        if (is_network_admin()) {
820
-            $this->_wp_page_slug .= '-network';
821
-        }
822
-    }
823
-
824
-
825
-    /**
826
-     * _verify_routes
827
-     * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
828
-     * we know if we need to drop out.
829
-     *
830
-     * @return bool
831
-     * @throws EE_Error
832
-     */
833
-    protected function _verify_routes()
834
-    {
835
-        if (! $this->_current_page && ! defined('DOING_AJAX')) {
836
-            return false;
837
-        }
838
-        $this->_route = false;
839
-        // check that the page_routes array is not empty
840
-        if (empty($this->_page_routes)) {
841
-            // user error msg
842
-            $error_msg = sprintf(
843
-                esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
844
-                $this->_admin_page_title
845
-            );
846
-            // developer error msg
847
-            $error_msg .= '||' . $error_msg
848
-                          . esc_html__(
849
-                              ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
850
-                              'event_espresso'
851
-                          );
852
-            throw new EE_Error($error_msg);
853
-        }
854
-        // and that the requested page route exists
855
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
856
-            $this->_route = $this->_page_routes[ $this->_req_action ];
857
-            $this->_route_config = isset($this->_page_config[ $this->_req_action ])
858
-                ? $this->_page_config[ $this->_req_action ] : array();
859
-        } else {
860
-            // user error msg
861
-            $error_msg = sprintf(
862
-                esc_html__(
863
-                    'The requested page route does not exist for the %s admin page.',
864
-                    'event_espresso'
865
-                ),
866
-                $this->_admin_page_title
867
-            );
868
-            // developer error msg
869
-            $error_msg .= '||' . $error_msg
870
-                          . sprintf(
871
-                              esc_html__(
872
-                                  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
873
-                                  'event_espresso'
874
-                              ),
875
-                              $this->_req_action
876
-                          );
877
-            throw new EE_Error($error_msg);
878
-        }
879
-        // and that a default route exists
880
-        if (! array_key_exists('default', $this->_page_routes)) {
881
-            // user error msg
882
-            $error_msg = sprintf(
883
-                esc_html__(
884
-                    'A default page route has not been set for the % admin page.',
885
-                    'event_espresso'
886
-                ),
887
-                $this->_admin_page_title
888
-            );
889
-            // developer error msg
890
-            $error_msg .= '||' . $error_msg
891
-                          . esc_html__(
892
-                              ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
893
-                              'event_espresso'
894
-                          );
895
-            throw new EE_Error($error_msg);
896
-        }
897
-
898
-        // first lets' catch if the UI request has EVER been set.
899
-        if ($this->_is_UI_request === null) {
900
-            // lets set if this is a UI request or not.
901
-            $this->_is_UI_request = ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true;
902
-            // wait a minute... we might have a noheader in the route array
903
-            $this->_is_UI_request = is_array($this->_route)
904
-                                    && isset($this->_route['noheader'])
905
-                                    && $this->_route['noheader'] ? false : $this->_is_UI_request;
906
-        }
907
-        $this->_set_current_labels();
908
-        return true;
909
-    }
910
-
911
-
912
-    /**
913
-     * this method simply verifies a given route and makes sure its an actual route available for the loaded page
914
-     *
915
-     * @param  string $route the route name we're verifying
916
-     * @return mixed (bool|Exception)      we'll throw an exception if this isn't a valid route.
917
-     * @throws EE_Error
918
-     */
919
-    protected function _verify_route($route)
920
-    {
921
-        if (array_key_exists($this->_req_action, $this->_page_routes)) {
922
-            return true;
923
-        }
924
-        // user error msg
925
-        $error_msg = sprintf(
926
-            esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
927
-            $this->_admin_page_title
928
-        );
929
-        // developer error msg
930
-        $error_msg .= '||' . $error_msg
931
-                      . sprintf(
932
-                          esc_html__(
933
-                              ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
934
-                              'event_espresso'
935
-                          ),
936
-                          $route
937
-                      );
938
-        throw new EE_Error($error_msg);
939
-    }
940
-
941
-
942
-    /**
943
-     * perform nonce verification
944
-     * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
945
-     * using this method (and save retyping!)
946
-     *
947
-     * @param string $nonce     The nonce sent
948
-     * @param string $nonce_ref The nonce reference string (name0)
949
-     * @return void
950
-     * @throws EE_Error
951
-     * @throws InvalidArgumentException
952
-     * @throws InvalidDataTypeException
953
-     * @throws InvalidInterfaceException
954
-     */
955
-    protected function _verify_nonce($nonce, $nonce_ref)
956
-    {
957
-        // verify nonce against expected value
958
-        if (! wp_verify_nonce($nonce, $nonce_ref)) {
959
-            // these are not the droids you are looking for !!!
960
-            $msg = sprintf(
961
-                esc_html__('%sNonce Fail.%s', 'event_espresso'),
962
-                '<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">',
963
-                '</a>'
964
-            );
965
-            if (WP_DEBUG) {
966
-                $msg .= "\n  "
967
-                        . sprintf(
968
-                            esc_html__(
969
-                                'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
970
-                                'event_espresso'
971
-                            ),
972
-                            EE_Admin_Page::class
973
-                        );
974
-            }
975
-            if (! defined('DOING_AJAX')) {
976
-                wp_die($msg);
977
-            } else {
978
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
979
-                $this->_return_json();
980
-            }
981
-        }
982
-    }
983
-
984
-
985
-    /**
986
-     * _route_admin_request()
987
-     * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
988
-     * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
989
-     * in the page routes and then will try to load the corresponding method.
990
-     *
991
-     * @return void
992
-     * @throws EE_Error
993
-     * @throws InvalidArgumentException
994
-     * @throws InvalidDataTypeException
995
-     * @throws InvalidInterfaceException
996
-     * @throws ReflectionException
997
-     */
998
-    protected function _route_admin_request()
999
-    {
1000
-        if (! $this->_is_UI_request) {
1001
-            $this->_verify_routes();
1002
-        }
1003
-        $nonce_check = isset($this->_route_config['require_nonce'])
1004
-            ? $this->_route_config['require_nonce']
1005
-            : true;
1006
-        if ($this->_req_action !== 'default' && $nonce_check) {
1007
-            // set nonce from post data
1008
-            $nonce = isset($this->_req_data[ $this->_req_nonce ])
1009
-                ? sanitize_text_field($this->_req_data[ $this->_req_nonce ])
1010
-                : '';
1011
-            $this->_verify_nonce($nonce, $this->_req_nonce);
1012
-        }
1013
-        // set the nav_tabs array but ONLY if this is  UI_request
1014
-        if ($this->_is_UI_request) {
1015
-            $this->_set_nav_tabs();
1016
-        }
1017
-        // grab callback function
1018
-        $func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1019
-        // check if callback has args
1020
-        $args = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
1021
-        $error_msg = '';
1022
-        // action right before calling route
1023
-        // (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1024
-        if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1025
-            do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1026
-        }
1027
-        // right before calling the route, let's remove _wp_http_referer from the
1028
-        // $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
1029
-        $_SERVER['REQUEST_URI'] = remove_query_arg(
1030
-            '_wp_http_referer',
1031
-            wp_unslash($_SERVER['REQUEST_URI'])
1032
-        );
1033
-        if (! empty($func)) {
1034
-            if (is_array($func)) {
1035
-                list($class, $method) = $func;
1036
-            } elseif (strpos($func, '::') !== false) {
1037
-                list($class, $method) = explode('::', $func);
1038
-            } else {
1039
-                $class = $this;
1040
-                $method = $func;
1041
-            }
1042
-            if (! (is_object($class) && $class === $this)) {
1043
-                // send along this admin page object for access by addons.
1044
-                $args['admin_page_object'] = $this;
1045
-            }
1046
-            // is it a method on a class that doesn't work?
1047
-            if (((method_exists($class, $method)
1048
-                  && call_user_func_array(array($class, $method), $args) === false)
1049
-                 && (// is it a standalone function that doesn't work?
1050
-                     function_exists($method)
1051
-                     && call_user_func_array(
1052
-                         $func,
1053
-                         array_merge(array('admin_page_object' => $this), $args)
1054
-                     ) === false
1055
-                 )) || (// is it neither a class method NOR a standalone function?
1056
-                    ! function_exists($method)
1057
-                    && ! method_exists($class, $method)
1058
-                )
1059
-            ) {
1060
-                // user error msg
1061
-                $error_msg = esc_html__(
1062
-                    'An error occurred. The  requested page route could not be found.',
1063
-                    'event_espresso'
1064
-                );
1065
-                // developer error msg
1066
-                $error_msg .= '||';
1067
-                $error_msg .= sprintf(
1068
-                    esc_html__(
1069
-                        'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1070
-                        'event_espresso'
1071
-                    ),
1072
-                    $method
1073
-                );
1074
-            }
1075
-            if (! empty($error_msg)) {
1076
-                throw new EE_Error($error_msg);
1077
-            }
1078
-        }
1079
-        // if we've routed and this route has a no headers route AND a sent_headers_route,
1080
-        // then we need to reset the routing properties to the new route.
1081
-        // 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.
1082
-        if ($this->_is_UI_request === false
1083
-            && is_array($this->_route)
1084
-            && ! empty($this->_route['headers_sent_route'])
1085
-        ) {
1086
-            $this->_reset_routing_properties($this->_route['headers_sent_route']);
1087
-        }
1088
-    }
1089
-
1090
-
1091
-    /**
1092
-     * This method just allows the resetting of page properties in the case where a no headers
1093
-     * route redirects to a headers route in its route config.
1094
-     *
1095
-     * @since   4.3.0
1096
-     * @param  string $new_route New (non header) route to redirect to.
1097
-     * @return   void
1098
-     * @throws ReflectionException
1099
-     * @throws InvalidArgumentException
1100
-     * @throws InvalidInterfaceException
1101
-     * @throws InvalidDataTypeException
1102
-     * @throws EE_Error
1103
-     */
1104
-    protected function _reset_routing_properties($new_route)
1105
-    {
1106
-        $this->_is_UI_request = true;
1107
-        // now we set the current route to whatever the headers_sent_route is set at
1108
-        $this->_req_data['action'] = $new_route;
1109
-        // rerun page setup
1110
-        $this->_page_setup();
1111
-    }
1112
-
1113
-
1114
-    /**
1115
-     * _add_query_arg
1116
-     * adds nonce to array of arguments then calls WP add_query_arg function
1117
-     *(internally just uses EEH_URL's function with the same name)
1118
-     *
1119
-     * @param array  $args
1120
-     * @param string $url
1121
-     * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1122
-     *                                        generated url in an associative array indexed by the key 'wp_referer';
1123
-     *                                        Example usage: If the current page is:
1124
-     *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1125
-     *                                        &action=default&event_id=20&month_range=March%202015
1126
-     *                                        &_wpnonce=5467821
1127
-     *                                        and you call:
1128
-     *                                        EE_Admin_Page::add_query_args_and_nonce(
1129
-     *                                        array(
1130
-     *                                        'action' => 'resend_something',
1131
-     *                                        'page=>espresso_registrations'
1132
-     *                                        ),
1133
-     *                                        $some_url,
1134
-     *                                        true
1135
-     *                                        );
1136
-     *                                        It will produce a url in this structure:
1137
-     *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1138
-     *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1139
-     *                                        month_range]=March%202015
1140
-     * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1141
-     * @return string
1142
-     */
1143
-    public static function add_query_args_and_nonce(
1144
-        $args = array(),
1145
-        $url = '',
1146
-        $sticky = false,
1147
-        $exclude_nonce = false
1148
-    ) {
1149
-        // if there is a _wp_http_referer include the values from the request but only if sticky = true
1150
-        if ($sticky) {
1151
-            $request = $_REQUEST;
1152
-            unset($request['_wp_http_referer'], $request['wp_referer']);
1153
-            foreach ($request as $key => $value) {
1154
-                // do not add nonces
1155
-                if (strpos($key, 'nonce') !== false) {
1156
-                    continue;
1157
-                }
1158
-                $args[ 'wp_referer[' . $key . ']' ] = $value;
1159
-            }
1160
-        }
1161
-        return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * This returns a generated link that will load the related help tab.
1167
-     *
1168
-     * @param  string $help_tab_id the id for the connected help tab
1169
-     * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
1170
-     * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
1171
-     * @uses EEH_Template::get_help_tab_link()
1172
-     * @return string              generated link
1173
-     */
1174
-    protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1175
-    {
1176
-        return EEH_Template::get_help_tab_link(
1177
-            $help_tab_id,
1178
-            $this->page_slug,
1179
-            $this->_req_action,
1180
-            $icon_style,
1181
-            $help_text
1182
-        );
1183
-    }
1184
-
1185
-
1186
-    /**
1187
-     * _add_help_tabs
1188
-     * Note child classes define their help tabs within the page_config array.
1189
-     *
1190
-     * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1191
-     * @return void
1192
-     * @throws DomainException
1193
-     * @throws EE_Error
1194
-     * @throws ReflectionException
1195
-     */
1196
-    protected function _add_help_tabs()
1197
-    {
1198
-        $tour_buttons = '';
1199
-        if (isset($this->_page_config[ $this->_req_action ])) {
1200
-            $config = $this->_page_config[ $this->_req_action ];
1201
-            // is there a help tour for the current route?  if there is let's setup the tour buttons
1202
-            if (isset($this->_help_tour[ $this->_req_action ])) {
1203
-                $tb = array();
1204
-                $tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1205
-                foreach ($this->_help_tour['tours'] as $tour) {
1206
-                    // if this is the end tour then we don't need to setup a button
1207
-                    if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1208
-                        continue;
1209
-                    }
1210
-                    $tb[] = '<button id="trigger-tour-'
1211
-                            . $tour->get_slug()
1212
-                            . '" class="button-primary trigger-ee-help-tour">'
1213
-                            . $tour->get_label()
1214
-                            . '</button>';
1215
-                }
1216
-                $tour_buttons .= implode('<br />', $tb);
1217
-                $tour_buttons .= '</div></div>';
1218
-            }
1219
-            // let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1220
-            if (is_array($config) && isset($config['help_sidebar'])) {
1221
-                // check that the callback given is valid
1222
-                if (! method_exists($this, $config['help_sidebar'])) {
1223
-                    throw new EE_Error(
1224
-                        sprintf(
1225
-                            esc_html__(
1226
-                                'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1227
-                                'event_espresso'
1228
-                            ),
1229
-                            $config['help_sidebar'],
1230
-                            get_class($this)
1231
-                        )
1232
-                    );
1233
-                }
1234
-                $content = apply_filters(
1235
-                    'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1236
-                    $this->{$config['help_sidebar']}()
1237
-                );
1238
-                $content .= $tour_buttons; // add help tour buttons.
1239
-                // do we have any help tours setup?  Cause if we do we want to add the buttons
1240
-                $this->_current_screen->set_help_sidebar($content);
1241
-            }
1242
-            // if there ARE tour buttons...
1243
-            if (! empty($tour_buttons)) {
1244
-                // if we DON'T have config help sidebar then we'll just add the tour buttons to the sidebar.
1245
-                if (! isset($config['help_sidebar'])) {
1246
-                    $this->_current_screen->set_help_sidebar($tour_buttons);
1247
-                }
1248
-                // handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1249
-                if (! isset($config['help_tabs'])) {
1250
-                    $_ht['id'] = $this->page_slug;
1251
-                    $_ht['title'] = esc_html__('Help Tours', 'event_espresso');
1252
-                    $_ht['content'] = '<p>'
1253
-                                      . esc_html__(
1254
-                                          'The buttons to the right allow you to start/restart any help tours available for this page',
1255
-                                          'event_espresso'
1256
-                                      ) . '</p>';
1257
-                    $this->_current_screen->add_help_tab($_ht);
1258
-                }
1259
-            }
1260
-            if (! isset($config['help_tabs'])) {
1261
-                return;
1262
-            } //no help tabs for this route
1263
-            foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1264
-                // we're here so there ARE help tabs!
1265
-                // make sure we've got what we need
1266
-                if (! isset($cfg['title'])) {
1267
-                    throw new EE_Error(
1268
-                        esc_html__(
1269
-                            'The _page_config array is not set up properly for help tabs.  It is missing a title',
1270
-                            'event_espresso'
1271
-                        )
1272
-                    );
1273
-                }
1274
-                if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1275
-                    throw new EE_Error(
1276
-                        esc_html__(
1277
-                            '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',
1278
-                            'event_espresso'
1279
-                        )
1280
-                    );
1281
-                }
1282
-                // first priority goes to content.
1283
-                if (! empty($cfg['content'])) {
1284
-                    $content = ! empty($cfg['content']) ? $cfg['content'] : null;
1285
-                    // second priority goes to filename
1286
-                } elseif (! empty($cfg['filename'])) {
1287
-                    $file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1288
-                    // 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)
1289
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1290
-                                                             . basename($this->_get_dir())
1291
-                                                             . '/help_tabs/'
1292
-                                                             . $cfg['filename']
1293
-                                                             . '.help_tab.php' : $file_path;
1294
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1295
-                    if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1296
-                        EE_Error::add_error(
1297
-                            sprintf(
1298
-                                esc_html__(
1299
-                                    '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',
1300
-                                    'event_espresso'
1301
-                                ),
1302
-                                $tab_id,
1303
-                                key($config),
1304
-                                $file_path
1305
-                            ),
1306
-                            __FILE__,
1307
-                            __FUNCTION__,
1308
-                            __LINE__
1309
-                        );
1310
-                        return;
1311
-                    }
1312
-                    $template_args['admin_page_obj'] = $this;
1313
-                    $content = EEH_Template::display_template(
1314
-                        $file_path,
1315
-                        $template_args,
1316
-                        true
1317
-                    );
1318
-                } else {
1319
-                    $content = '';
1320
-                }
1321
-                // check if callback is valid
1322
-                if (empty($content) && (
1323
-                        ! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1324
-                    )
1325
-                ) {
1326
-                    EE_Error::add_error(
1327
-                        sprintf(
1328
-                            esc_html__(
1329
-                                '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.',
1330
-                                'event_espresso'
1331
-                            ),
1332
-                            $cfg['title']
1333
-                        ),
1334
-                        __FILE__,
1335
-                        __FUNCTION__,
1336
-                        __LINE__
1337
-                    );
1338
-                    return;
1339
-                }
1340
-                // setup config array for help tab method
1341
-                $id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1342
-                $_ht = array(
1343
-                    'id'       => $id,
1344
-                    'title'    => $cfg['title'],
1345
-                    'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1346
-                    'content'  => $content,
1347
-                );
1348
-                $this->_current_screen->add_help_tab($_ht);
1349
-            }
1350
-        }
1351
-    }
1352
-
1353
-
1354
-    /**
1355
-     * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1356
-     * an array with properties for setting up usage of the joyride plugin
1357
-     *
1358
-     * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1359
-     * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1360
-     *         _set_page_config() comments
1361
-     * @return void
1362
-     * @throws EE_Error
1363
-     * @throws InvalidArgumentException
1364
-     * @throws InvalidDataTypeException
1365
-     * @throws InvalidInterfaceException
1366
-     * @throws ReflectionException
1367
-     */
1368
-    protected function _add_help_tour()
1369
-    {
1370
-        $tours = array();
1371
-        $this->_help_tour = array();
1372
-        // exit early if help tours are turned off globally
1373
-        if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1374
-            || ! EE_Registry::instance()->CFG->admin->help_tour_activation
1375
-        ) {
1376
-            return;
1377
-        }
1378
-        // loop through _page_config to find any help_tour defined
1379
-        foreach ($this->_page_config as $route => $config) {
1380
-            // we're only going to set things up for this route
1381
-            if ($route !== $this->_req_action) {
1382
-                continue;
1383
-            }
1384
-            if (isset($config['help_tour'])) {
1385
-                foreach ($config['help_tour'] as $tour) {
1386
-                    $file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1387
-                    // let's see if we can get that file...
1388
-                    // if not its possible this is a decaf route not set in caffeinated
1389
-                    // so lets try and get the caffeinated equivalent
1390
-                    $file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1391
-                                                             . basename($this->_get_dir())
1392
-                                                             . '/help_tours/'
1393
-                                                             . $tour
1394
-                                                             . '.class.php' : $file_path;
1395
-                    // if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1396
-                    if (! is_readable($file_path)) {
1397
-                        EE_Error::add_error(
1398
-                            sprintf(
1399
-                                esc_html__(
1400
-                                    'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1401
-                                    'event_espresso'
1402
-                                ),
1403
-                                $file_path,
1404
-                                $tour
1405
-                            ),
1406
-                            __FILE__,
1407
-                            __FUNCTION__,
1408
-                            __LINE__
1409
-                        );
1410
-                        return;
1411
-                    }
1412
-                    require_once $file_path;
1413
-                    if (! class_exists($tour)) {
1414
-                        $error_msg = [];
1415
-                        $error_msg[] = sprintf(
1416
-                            esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1417
-                            $tour
1418
-                        );
1419
-                        $error_msg[] = $error_msg[0] . "\r\n"
1420
-                                       . sprintf(
1421
-                                           esc_html__(
1422
-                                               'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1423
-                                               'event_espresso'
1424
-                                           ),
1425
-                                           $tour,
1426
-                                           '<br />',
1427
-                                           $tour,
1428
-                                           $this->_req_action,
1429
-                                           get_class($this)
1430
-                                       );
1431
-                        throw new EE_Error(implode('||', $error_msg));
1432
-                    }
1433
-                    $tour_obj = new $tour($this->_is_caf);
1434
-                    $tours[] = $tour_obj;
1435
-                    $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1436
-                }
1437
-                // let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1438
-                $end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1439
-                $tours[] = $end_stop_tour;
1440
-                $this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1441
-            }
1442
-        }
1443
-
1444
-        if (! empty($tours)) {
1445
-            $this->_help_tour['tours'] = $tours;
1446
-        }
1447
-        // that's it!  Now that the $_help_tours property is set (or not)
1448
-        // the scripts and html should be taken care of automatically.
1449
-
1450
-        /**
1451
-         * Allow extending the help tours variable.
1452
-         *
1453
-         * @param array $_help_tour The array containing all help tour information to be displayed.
1454
-         */
1455
-        $this->_help_tour = apply_filters('FHEE__EE_Admin_Page___add_help_tour___help_tour', $this->_help_tour);
1456
-    }
1457
-
1458
-
1459
-    /**
1460
-     * This simply sets up any qtips that have been defined in the page config
1461
-     *
1462
-     * @return void
1463
-     * @throws ReflectionException
1464
-     * @throws EE_Error
1465
-     */
1466
-    protected function _add_qtips()
1467
-    {
1468
-        if (isset($this->_route_config['qtips'])) {
1469
-            $qtips = (array) $this->_route_config['qtips'];
1470
-            // load qtip loader
1471
-            $path = array(
1472
-                $this->_get_dir() . '/qtips/',
1473
-                EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1474
-            );
1475
-            $qtip_loader = EEH_Qtip_Loader::instance();
1476
-            if ($qtip_loader instanceof EEH_Qtip_Loader) {
1477
-                $qtip_loader->register($qtips, $path);
1478
-            }
1479
-        }
1480
-    }
1481
-
1482
-
1483
-    /**
1484
-     * _set_nav_tabs
1485
-     * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1486
-     * wish to add additional tabs or modify accordingly.
1487
-     *
1488
-     * @return void
1489
-     * @throws InvalidArgumentException
1490
-     * @throws InvalidInterfaceException
1491
-     * @throws InvalidDataTypeException
1492
-     */
1493
-    protected function _set_nav_tabs()
1494
-    {
1495
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1496
-        $i = 0;
1497
-        foreach ($this->_page_config as $slug => $config) {
1498
-            if (! is_array($config)
1499
-                || (
1500
-                    is_array($config)
1501
-                    && (
1502
-                        (isset($config['nav']) && ! $config['nav'])
1503
-                        || ! isset($config['nav'])
1504
-                    )
1505
-                )
1506
-            ) {
1507
-                continue;
1508
-            }
1509
-            // no nav tab for this config
1510
-            // check for persistent flag
1511
-            if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1512
-                // nav tab is only to appear when route requested.
1513
-                continue;
1514
-            }
1515
-            if (! $this->check_user_access($slug, true)) {
1516
-                // no nav tab because current user does not have access.
1517
-                continue;
1518
-            }
1519
-            $css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1520
-            $this->_nav_tabs[ $slug ] = array(
1521
-                'url'       => isset($config['nav']['url'])
1522
-                    ? $config['nav']['url']
1523
-                    : EE_Admin_Page::add_query_args_and_nonce(
1524
-                        array('action' => $slug),
1525
-                        $this->_admin_base_url
1526
-                    ),
1527
-                'link_text' => isset($config['nav']['label'])
1528
-                    ? $config['nav']['label']
1529
-                    : ucwords(
1530
-                        str_replace('_', ' ', $slug)
1531
-                    ),
1532
-                'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1533
-                'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1534
-            );
1535
-            $i++;
1536
-        }
1537
-        // if $this->_nav_tabs is empty then lets set the default
1538
-        if (empty($this->_nav_tabs)) {
1539
-            $this->_nav_tabs[ $this->_default_nav_tab_name ] = array(
1540
-                'url'       => $this->_admin_base_url,
1541
-                'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1542
-                'css_class' => 'nav-tab-active',
1543
-                'order'     => 10,
1544
-            );
1545
-        }
1546
-        // now let's sort the tabs according to order
1547
-        usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1548
-    }
1549
-
1550
-
1551
-    /**
1552
-     * _set_current_labels
1553
-     * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1554
-     * property array
1555
-     *
1556
-     * @return void
1557
-     */
1558
-    private function _set_current_labels()
1559
-    {
1560
-        if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1561
-            foreach ($this->_route_config['labels'] as $label => $text) {
1562
-                if (is_array($text)) {
1563
-                    foreach ($text as $sublabel => $subtext) {
1564
-                        $this->_labels[ $label ][ $sublabel ] = $subtext;
1565
-                    }
1566
-                } else {
1567
-                    $this->_labels[ $label ] = $text;
1568
-                }
1569
-            }
1570
-        }
1571
-    }
1572
-
1573
-
1574
-    /**
1575
-     *        verifies user access for this admin page
1576
-     *
1577
-     * @param string $route_to_check if present then the capability for the route matching this string is checked.
1578
-     * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1579
-     *                               return false if verify fail.
1580
-     * @return bool
1581
-     * @throws InvalidArgumentException
1582
-     * @throws InvalidDataTypeException
1583
-     * @throws InvalidInterfaceException
1584
-     */
1585
-    public function check_user_access($route_to_check = '', $verify_only = false)
1586
-    {
1587
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1588
-        $route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1589
-        $capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1590
-                      && is_array(
1591
-                          $this->_page_routes[ $route_to_check ]
1592
-                      )
1593
-                      && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1594
-            ? $this->_page_routes[ $route_to_check ]['capability'] : null;
1595
-        if (empty($capability) && empty($route_to_check)) {
1596
-            $capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1597
-                : $this->_route['capability'];
1598
-        } else {
1599
-            $capability = empty($capability) ? 'manage_options' : $capability;
1600
-        }
1601
-        $id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1602
-        if (! defined('DOING_AJAX')
1603
-            && (
1604
-                ! function_exists('is_admin')
1605
-                || ! EE_Registry::instance()->CAP->current_user_can(
1606
-                    $capability,
1607
-                    $this->page_slug
1608
-                    . '_'
1609
-                    . $route_to_check,
1610
-                    $id
1611
-                )
1612
-            )
1613
-        ) {
1614
-            if ($verify_only) {
1615
-                return false;
1616
-            }
1617
-            if (is_user_logged_in()) {
1618
-                wp_die(__('You do not have access to this route.', 'event_espresso'));
1619
-            } else {
1620
-                return false;
1621
-            }
1622
-        }
1623
-        return true;
1624
-    }
1625
-
1626
-
1627
-    /**
1628
-     * admin_init_global
1629
-     * This runs all the code that we want executed within the WP admin_init hook.
1630
-     * This method executes for ALL EE Admin pages.
1631
-     *
1632
-     * @return void
1633
-     */
1634
-    public function admin_init_global()
1635
-    {
1636
-    }
1637
-
1638
-
1639
-    /**
1640
-     * wp_loaded_global
1641
-     * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1642
-     * EE_Admin page and will execute on every EE Admin Page load
1643
-     *
1644
-     * @return void
1645
-     */
1646
-    public function wp_loaded()
1647
-    {
1648
-    }
1649
-
1650
-
1651
-    /**
1652
-     * admin_notices
1653
-     * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1654
-     * ALL EE_Admin pages.
1655
-     *
1656
-     * @return void
1657
-     */
1658
-    public function admin_notices_global()
1659
-    {
1660
-        $this->_display_no_javascript_warning();
1661
-        $this->_display_espresso_notices();
1662
-    }
1663
-
1664
-
1665
-    public function network_admin_notices_global()
1666
-    {
1667
-        $this->_display_no_javascript_warning();
1668
-        $this->_display_espresso_notices();
1669
-    }
1670
-
1671
-
1672
-    /**
1673
-     * admin_footer_scripts_global
1674
-     * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1675
-     * will apply on ALL EE_Admin pages.
1676
-     *
1677
-     * @return void
1678
-     */
1679
-    public function admin_footer_scripts_global()
1680
-    {
1681
-        $this->_add_admin_page_ajax_loading_img();
1682
-        $this->_add_admin_page_overlay();
1683
-        // if metaboxes are present we need to add the nonce field
1684
-        if (isset($this->_route_config['metaboxes'])
1685
-            || isset($this->_route_config['list_table'])
1686
-            || (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1687
-        ) {
1688
-            wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1689
-            wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1690
-        }
1691
-    }
1692
-
1693
-
1694
-    /**
1695
-     * admin_footer_global
1696
-     * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1697
-     * This particular method will apply on ALL EE_Admin Pages.
1698
-     *
1699
-     * @return void
1700
-     * @throws InvalidArgumentException
1701
-     * @throws InvalidDataTypeException
1702
-     * @throws InvalidInterfaceException
1703
-     */
1704
-    public function admin_footer_global()
1705
-    {
1706
-        // dialog container for dialog helper
1707
-        $d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1708
-        $d_cont .= '<div class="ee-notices"></div>';
1709
-        $d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1710
-        $d_cont .= '</div>';
1711
-        echo $d_cont;
1712
-        // help tour stuff?
1713
-        if (isset($this->_help_tour[ $this->_req_action ])) {
1714
-            echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1715
-        }
1716
-        // current set timezone for timezone js
1717
-        echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1718
-    }
1719
-
1720
-
1721
-    /**
1722
-     * This function sees if there is a method for help popup content existing for the given route.  If there is then
1723
-     * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1724
-     * help popups then in your templates or your content you set "triggers" for the content using the
1725
-     * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1726
-     * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1727
-     * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1728
-     * for the
1729
-     * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1730
-     * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1731
-     *    'help_trigger_id' => array(
1732
-     *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1733
-     *        'content' => esc_html__('localized content for popup', 'event_espresso')
1734
-     *    )
1735
-     * );
1736
-     * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1737
-     *
1738
-     * @param array $help_array
1739
-     * @param bool  $display
1740
-     * @return string content
1741
-     * @throws DomainException
1742
-     * @throws EE_Error
1743
-     */
1744
-    protected function _set_help_popup_content($help_array = array(), $display = false)
1745
-    {
1746
-        $content = '';
1747
-        $help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1748
-        // loop through the array and setup content
1749
-        foreach ($help_array as $trigger => $help) {
1750
-            // make sure the array is setup properly
1751
-            if (! isset($help['title'], $help['content'])) {
1752
-                throw new EE_Error(
1753
-                    esc_html__(
1754
-                        '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',
1755
-                        'event_espresso'
1756
-                    )
1757
-                );
1758
-            }
1759
-            // we're good so let'd setup the template vars and then assign parsed template content to our content.
1760
-            $template_args = array(
1761
-                'help_popup_id'      => $trigger,
1762
-                'help_popup_title'   => $help['title'],
1763
-                'help_popup_content' => $help['content'],
1764
-            );
1765
-            $content .= EEH_Template::display_template(
1766
-                EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1767
-                $template_args,
1768
-                true
1769
-            );
1770
-        }
1771
-        if ($display) {
1772
-            echo $content;
1773
-            return '';
1774
-        }
1775
-        return $content;
1776
-    }
1777
-
1778
-
1779
-    /**
1780
-     * All this does is retrieve the help content array if set by the EE_Admin_Page child
1781
-     *
1782
-     * @return array properly formatted array for help popup content
1783
-     * @throws EE_Error
1784
-     */
1785
-    private function _get_help_content()
1786
-    {
1787
-        // what is the method we're looking for?
1788
-        $method_name = '_help_popup_content_' . $this->_req_action;
1789
-        // if method doesn't exist let's get out.
1790
-        if (! method_exists($this, $method_name)) {
1791
-            return array();
1792
-        }
1793
-        // k we're good to go let's retrieve the help array
1794
-        $help_array = $this->{$method_name}();
1795
-        // make sure we've got an array!
1796
-        if (! is_array($help_array)) {
1797
-            throw new EE_Error(
1798
-                esc_html__(
1799
-                    'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1800
-                    'event_espresso'
1801
-                )
1802
-            );
1803
-        }
1804
-        return $help_array;
1805
-    }
1806
-
1807
-
1808
-    /**
1809
-     * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1810
-     * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1811
-     * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1812
-     *
1813
-     * @param string  $trigger_id reference for retrieving the trigger content for the popup
1814
-     * @param boolean $display    if false then we return the trigger string
1815
-     * @param array   $dimensions an array of dimensions for the box (array(h,w))
1816
-     * @return string
1817
-     * @throws DomainException
1818
-     * @throws EE_Error
1819
-     */
1820
-    protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1821
-    {
1822
-        if (defined('DOING_AJAX')) {
1823
-            return '';
1824
-        }
1825
-        // 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
1826
-        $help_array = $this->_get_help_content();
1827
-        $help_content = '';
1828
-        if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1829
-            $help_array[ $trigger_id ] = array(
1830
-                'title'   => esc_html__('Missing Content', 'event_espresso'),
1831
-                'content' => esc_html__(
1832
-                    '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.)',
1833
-                    'event_espresso'
1834
-                ),
1835
-            );
1836
-            $help_content = $this->_set_help_popup_content($help_array);
1837
-        }
1838
-        // let's setup the trigger
1839
-        $content = '<a class="ee-dialog" href="?height='
1840
-                   . $dimensions[0]
1841
-                   . '&width='
1842
-                   . $dimensions[1]
1843
-                   . '&inlineId='
1844
-                   . $trigger_id
1845
-                   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1846
-        $content .= $help_content;
1847
-        if ($display) {
1848
-            echo $content;
1849
-            return '';
1850
-        }
1851
-        return $content;
1852
-    }
1853
-
1854
-
1855
-    /**
1856
-     * _add_global_screen_options
1857
-     * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1858
-     * This particular method will add_screen_options on ALL EE_Admin Pages
1859
-     *
1860
-     * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1861
-     *         see also WP_Screen object documents...
1862
-     * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1863
-     * @abstract
1864
-     * @return void
1865
-     */
1866
-    private function _add_global_screen_options()
1867
-    {
1868
-    }
1869
-
1870
-
1871
-    /**
1872
-     * _add_global_feature_pointers
1873
-     * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1874
-     * This particular method will implement feature pointers for ALL EE_Admin pages.
1875
-     * Note: this is just a placeholder for now.  Implementation will come down the road
1876
-     *
1877
-     * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1878
-     *         extended) also see:
1879
-     * @link   http://eamann.com/tech/wordpress-portland/
1880
-     * @abstract
1881
-     * @return void
1882
-     */
1883
-    private function _add_global_feature_pointers()
1884
-    {
1885
-    }
1886
-
1887
-
1888
-    /**
1889
-     * load_global_scripts_styles
1890
-     * The scripts and styles enqueued in here will be loaded on every EE Admin page
1891
-     *
1892
-     * @return void
1893
-     * @throws EE_Error
1894
-     */
1895
-    public function load_global_scripts_styles()
1896
-    {
1897
-        // add debugging styles
1898
-        if (WP_DEBUG) {
1899
-            add_action('admin_head', array($this, 'add_xdebug_style'));
1900
-        }
1901
-        // taking care of metaboxes
1902
-        if (empty($this->_cpt_route)
1903
-            && (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1904
-        ) {
1905
-            wp_enqueue_script('dashboard');
1906
-        }
1907
-
1908
-        // LOCALIZED DATA
1909
-        // localize script for ajax lazy loading
1910
-        wp_localize_script(
1911
-            EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1912
-            'eeLazyLoadingContainers',
1913
-            apply_filters(
1914
-                'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1915
-                ['espresso_news_post_box_content']
1916
-            )
1917
-        );
1918
-        /**
1919
-         * help tour stuff
1920
-         */
1921
-        if (EE_Registry::instance()->CFG->admin->help_tour_activation && ! empty($this->_help_tour)) {
1922
-            add_filter('FHEE_load_joyride', '__return_true');
1923
-            $tours = array();
1924
-            // setup tours for the js tour object
1925
-            foreach ($this->_help_tour['tours'] as $tour) {
1926
-                if ($tour instanceof EE_Help_Tour) {
1927
-                    $tours[] = array(
1928
-                        'id'      => $tour->get_slug(),
1929
-                        'options' => $tour->get_options(),
1930
-                    );
1931
-                }
1932
-            }
1933
-            wp_localize_script(
1934
-                EspressoLegacyAdminAssetManager::JS_HANDLE_EE_HELP_TOUR,
1935
-                'EE_HELP_TOUR',
1936
-                ['tours' => $tours]
1937
-            );
1938
-            // admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
1939
-        }
1940
-    }
1941
-
1942
-
1943
-    /**
1944
-     *        admin_footer_scripts_eei18n_js_strings
1945
-     *
1946
-     * @return        void
1947
-     */
1948
-    public function admin_footer_scripts_eei18n_js_strings()
1949
-    {
1950
-        EE_Registry::$i18n_js_strings['ajax_url'] = WP_AJAX_URL;
1951
-        EE_Registry::$i18n_js_strings['confirm_delete'] = esc_html__(
1952
-            '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!!!',
1953
-            'event_espresso'
1954
-        );
1955
-        EE_Registry::$i18n_js_strings['January'] = esc_html__('January', 'event_espresso');
1956
-        EE_Registry::$i18n_js_strings['February'] = esc_html__('February', 'event_espresso');
1957
-        EE_Registry::$i18n_js_strings['March'] = esc_html__('March', 'event_espresso');
1958
-        EE_Registry::$i18n_js_strings['April'] = esc_html__('April', 'event_espresso');
1959
-        EE_Registry::$i18n_js_strings['May'] = esc_html__('May', 'event_espresso');
1960
-        EE_Registry::$i18n_js_strings['June'] = esc_html__('June', 'event_espresso');
1961
-        EE_Registry::$i18n_js_strings['July'] = esc_html__('July', 'event_espresso');
1962
-        EE_Registry::$i18n_js_strings['August'] = esc_html__('August', 'event_espresso');
1963
-        EE_Registry::$i18n_js_strings['September'] = esc_html__('September', 'event_espresso');
1964
-        EE_Registry::$i18n_js_strings['October'] = esc_html__('October', 'event_espresso');
1965
-        EE_Registry::$i18n_js_strings['November'] = esc_html__('November', 'event_espresso');
1966
-        EE_Registry::$i18n_js_strings['December'] = esc_html__('December', 'event_espresso');
1967
-        EE_Registry::$i18n_js_strings['Jan'] = esc_html__('Jan', 'event_espresso');
1968
-        EE_Registry::$i18n_js_strings['Feb'] = esc_html__('Feb', 'event_espresso');
1969
-        EE_Registry::$i18n_js_strings['Mar'] = esc_html__('Mar', 'event_espresso');
1970
-        EE_Registry::$i18n_js_strings['Apr'] = esc_html__('Apr', 'event_espresso');
1971
-        EE_Registry::$i18n_js_strings['May'] = esc_html__('May', 'event_espresso');
1972
-        EE_Registry::$i18n_js_strings['Jun'] = esc_html__('Jun', 'event_espresso');
1973
-        EE_Registry::$i18n_js_strings['Jul'] = esc_html__('Jul', 'event_espresso');
1974
-        EE_Registry::$i18n_js_strings['Aug'] = esc_html__('Aug', 'event_espresso');
1975
-        EE_Registry::$i18n_js_strings['Sep'] = esc_html__('Sep', 'event_espresso');
1976
-        EE_Registry::$i18n_js_strings['Oct'] = esc_html__('Oct', 'event_espresso');
1977
-        EE_Registry::$i18n_js_strings['Nov'] = esc_html__('Nov', 'event_espresso');
1978
-        EE_Registry::$i18n_js_strings['Dec'] = esc_html__('Dec', 'event_espresso');
1979
-        EE_Registry::$i18n_js_strings['Sunday'] = esc_html__('Sunday', 'event_espresso');
1980
-        EE_Registry::$i18n_js_strings['Monday'] = esc_html__('Monday', 'event_espresso');
1981
-        EE_Registry::$i18n_js_strings['Tuesday'] = esc_html__('Tuesday', 'event_espresso');
1982
-        EE_Registry::$i18n_js_strings['Wednesday'] = esc_html__('Wednesday', 'event_espresso');
1983
-        EE_Registry::$i18n_js_strings['Thursday'] = esc_html__('Thursday', 'event_espresso');
1984
-        EE_Registry::$i18n_js_strings['Friday'] = esc_html__('Friday', 'event_espresso');
1985
-        EE_Registry::$i18n_js_strings['Saturday'] = esc_html__('Saturday', 'event_espresso');
1986
-        EE_Registry::$i18n_js_strings['Sun'] = esc_html__('Sun', 'event_espresso');
1987
-        EE_Registry::$i18n_js_strings['Mon'] = esc_html__('Mon', 'event_espresso');
1988
-        EE_Registry::$i18n_js_strings['Tue'] = esc_html__('Tue', 'event_espresso');
1989
-        EE_Registry::$i18n_js_strings['Wed'] = esc_html__('Wed', 'event_espresso');
1990
-        EE_Registry::$i18n_js_strings['Thu'] = esc_html__('Thu', 'event_espresso');
1991
-        EE_Registry::$i18n_js_strings['Fri'] = esc_html__('Fri', 'event_espresso');
1992
-        EE_Registry::$i18n_js_strings['Sat'] = esc_html__('Sat', 'event_espresso');
1993
-    }
1994
-
1995
-
1996
-    /**
1997
-     *        load enhanced xdebug styles for ppl with failing eyesight
1998
-     *
1999
-     * @return        void
2000
-     */
2001
-    public function add_xdebug_style()
2002
-    {
2003
-        echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2004
-    }
2005
-
2006
-
2007
-    /************************/
2008
-    /** LIST TABLE METHODS **/
2009
-    /************************/
2010
-    /**
2011
-     * this sets up the list table if the current view requires it.
2012
-     *
2013
-     * @return void
2014
-     * @throws EE_Error
2015
-     * @throws InvalidArgumentException
2016
-     * @throws InvalidDataTypeException
2017
-     * @throws InvalidInterfaceException
2018
-     */
2019
-    protected function _set_list_table()
2020
-    {
2021
-        // first is this a list_table view?
2022
-        if (! isset($this->_route_config['list_table'])) {
2023
-            return;
2024
-        } //not a list_table view so get out.
2025
-        // list table functions are per view specific (because some admin pages might have more than one list table!)
2026
-        $list_table_view = '_set_list_table_views_' . $this->_req_action;
2027
-        if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2028
-            // user error msg
2029
-            $error_msg = esc_html__(
2030
-                'An error occurred. The requested list table views could not be found.',
2031
-                'event_espresso'
2032
-            );
2033
-            // developer error msg
2034
-            $error_msg .= '||'
2035
-                          . sprintf(
2036
-                              esc_html__(
2037
-                                  '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.',
2038
-                                  'event_espresso'
2039
-                              ),
2040
-                              $this->_req_action,
2041
-                              $list_table_view
2042
-                          );
2043
-            throw new EE_Error($error_msg);
2044
-        }
2045
-        // let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2046
-        $this->_views = apply_filters(
2047
-            'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2048
-            $this->_views
2049
-        );
2050
-        $this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2051
-        $this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2052
-        $this->_set_list_table_view();
2053
-        $this->_set_list_table_object();
2054
-    }
2055
-
2056
-
2057
-    /**
2058
-     * set current view for List Table
2059
-     *
2060
-     * @return void
2061
-     */
2062
-    protected function _set_list_table_view()
2063
-    {
2064
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2065
-        // looking at active items or dumpster diving ?
2066
-        if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2067
-            $this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2068
-        } else {
2069
-            $this->_view = sanitize_key($this->_req_data['status']);
2070
-        }
2071
-    }
2072
-
2073
-
2074
-    /**
2075
-     * _set_list_table_object
2076
-     * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2077
-     *
2078
-     * @throws InvalidInterfaceException
2079
-     * @throws InvalidArgumentException
2080
-     * @throws InvalidDataTypeException
2081
-     * @throws EE_Error
2082
-     * @throws InvalidInterfaceException
2083
-     */
2084
-    protected function _set_list_table_object()
2085
-    {
2086
-        if (isset($this->_route_config['list_table'])) {
2087
-            if (! class_exists($this->_route_config['list_table'])) {
2088
-                throw new EE_Error(
2089
-                    sprintf(
2090
-                        esc_html__(
2091
-                            '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.',
2092
-                            'event_espresso'
2093
-                        ),
2094
-                        $this->_route_config['list_table'],
2095
-                        get_class($this)
2096
-                    )
2097
-                );
2098
-            }
2099
-            $this->_list_table_object = $this->loader->getShared(
2100
-                $this->_route_config['list_table'],
2101
-                array($this)
2102
-            );
2103
-        }
2104
-    }
2105
-
2106
-
2107
-    /**
2108
-     * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2109
-     *
2110
-     * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2111
-     *                                                    urls.  The array should be indexed by the view it is being
2112
-     *                                                    added to.
2113
-     * @return array
2114
-     */
2115
-    public function get_list_table_view_RLs($extra_query_args = array())
2116
-    {
2117
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2118
-        if (empty($this->_views)) {
2119
-            $this->_views = array();
2120
-        }
2121
-        // cycle thru views
2122
-        foreach ($this->_views as $key => $view) {
2123
-            $query_args = array();
2124
-            // check for current view
2125
-            $this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2126
-            $query_args['action'] = $this->_req_action;
2127
-            $query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2128
-            $query_args['status'] = $view['slug'];
2129
-            // merge any other arguments sent in.
2130
-            if (isset($extra_query_args[ $view['slug'] ])) {
2131
-                foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2132
-                    $query_args[] = $extra_query_arg;
2133
-                }
2134
-            }
2135
-            $this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2136
-        }
2137
-        return $this->_views;
2138
-    }
2139
-
2140
-
2141
-    /**
2142
-     * _entries_per_page_dropdown
2143
-     * generates a drop down box for selecting the number of visible rows in an admin page list table
2144
-     *
2145
-     * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2146
-     *         WP does it.
2147
-     * @param int $max_entries total number of rows in the table
2148
-     * @return string
2149
-     */
2150
-    protected function _entries_per_page_dropdown($max_entries = 0)
2151
-    {
2152
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2153
-        $values = array(10, 25, 50, 100);
2154
-        $per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2155
-        if ($max_entries) {
2156
-            $values[] = $max_entries;
2157
-            sort($values);
2158
-        }
2159
-        $entries_per_page_dropdown = '
115
+	/**
116
+	 * Used to hold default query args for list table routes to help preserve stickiness of filters for carried out
117
+	 * actions.
118
+	 *
119
+	 * @since 4.6.x
120
+	 * @var array.
121
+	 */
122
+	protected $_default_route_query_args;
123
+
124
+	// set via request page and action args.
125
+	protected $_current_page;
126
+
127
+	protected $_current_view;
128
+
129
+	protected $_current_page_view_url;
130
+
131
+	// sanitized request action (and nonce)
132
+
133
+	/**
134
+	 * @var string $_req_action
135
+	 */
136
+	protected $_req_action;
137
+
138
+	/**
139
+	 * @var string $_req_nonce
140
+	 */
141
+	protected $_req_nonce;
142
+
143
+	// search related
144
+	protected $_search_btn_label;
145
+
146
+	protected $_search_box_callback;
147
+
148
+	/**
149
+	 * WP Current Screen object
150
+	 *
151
+	 * @var WP_Screen
152
+	 */
153
+	protected $_current_screen;
154
+
155
+	// for holding EE_Admin_Hooks object when needed (set via set_hook_object())
156
+	protected $_hook_obj;
157
+
158
+	// for holding incoming request data
159
+	protected $_req_data;
160
+
161
+	// yes / no array for admin form fields
162
+	protected $_yes_no_values = array();
163
+
164
+	// some default things shared by all child classes
165
+	protected $_default_espresso_metaboxes;
166
+
167
+	/**
168
+	 *    EE_Registry Object
169
+	 *
170
+	 * @var    EE_Registry
171
+	 */
172
+	protected $EE;
173
+
174
+
175
+	/**
176
+	 * This is just a property that flags whether the given route is a caffeinated route or not.
177
+	 *
178
+	 * @var boolean
179
+	 */
180
+	protected $_is_caf = false;
181
+
182
+
183
+	/**
184
+	 * @Constructor
185
+	 * @param bool $routing indicate whether we want to just load the object and handle routing or just load the object.
186
+	 * @throws InvalidArgumentException
187
+	 * @throws InvalidDataTypeException
188
+	 * @throws InvalidInterfaceException
189
+	 * @throws ReflectionException
190
+	 */
191
+	public function __construct($routing = true)
192
+	{
193
+		$this->loader = LoaderFactory::getLoader();
194
+		$this->admin_config = $this->loader->getShared('EE_Admin_Config');
195
+		if (strpos($this->_get_dir(), 'caffeinated') !== false) {
196
+			$this->_is_caf = true;
197
+		}
198
+		$this->_yes_no_values = array(
199
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
200
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
201
+		);
202
+		// set the _req_data property.
203
+		$this->_req_data = array_merge($_GET, $_POST);
204
+		// routing enabled?
205
+		$this->_routing = $routing;
206
+	}
207
+
208
+
209
+	/**
210
+	 * This logic used to be in the constructor, but that caused a chicken <--> egg scenario
211
+	 * for child classes that needed to set properties prior to these methods getting called,
212
+	 * but also needed the parent class to have its construction completed as well.
213
+	 * Bottom line is that constructors should ONLY be used for setting initial properties
214
+	 * and any complex initialization logic should only run after instantiation is complete.
215
+	 *
216
+	 * This method gets called immediately after construction from within
217
+	 *      EE_Admin_Page_Init::_initialize_admin_page()
218
+	 *
219
+	 * @throws EE_Error
220
+	 * @throws InvalidArgumentException
221
+	 * @throws InvalidDataTypeException
222
+	 * @throws InvalidInterfaceException
223
+	 * @throws ReflectionException
224
+	 * @since $VID:$
225
+	 */
226
+	public function initializePage()
227
+	{
228
+		// set initial page props (child method)
229
+		$this->_init_page_props();
230
+		// set global defaults
231
+		$this->_set_defaults();
232
+		// set early because incoming requests could be ajax related and we need to register those hooks.
233
+		$this->_global_ajax_hooks();
234
+		$this->_ajax_hooks();
235
+		// other_page_hooks have to be early too.
236
+		$this->_do_other_page_hooks();
237
+		// This just allows us to have extending classes do something specific
238
+		// before the parent constructor runs _page_setup().
239
+		if (method_exists($this, '_before_page_setup')) {
240
+			$this->_before_page_setup();
241
+		}
242
+		// set up page dependencies
243
+		$this->_page_setup();
244
+	}
245
+
246
+
247
+	/**
248
+	 * _init_page_props
249
+	 * Child classes use to set at least the following properties:
250
+	 * $page_slug.
251
+	 * $page_label.
252
+	 *
253
+	 * @abstract
254
+	 * @return void
255
+	 */
256
+	abstract protected function _init_page_props();
257
+
258
+
259
+	/**
260
+	 * _ajax_hooks
261
+	 * child classes put all their add_action('wp_ajax_{name_of_hook}') hooks in here.
262
+	 * Note: within the ajax callback methods.
263
+	 *
264
+	 * @abstract
265
+	 * @return void
266
+	 */
267
+	abstract protected function _ajax_hooks();
268
+
269
+
270
+	/**
271
+	 * _define_page_props
272
+	 * child classes define page properties in here.  Must include at least:
273
+	 * $_admin_base_url = base_url for all admin pages
274
+	 * $_admin_page_title = default admin_page_title for admin pages
275
+	 * $_labels = array of default labels for various automatically generated elements:
276
+	 *    array(
277
+	 *        'buttons' => array(
278
+	 *            'add' => esc_html__('label for add new button'),
279
+	 *            'edit' => esc_html__('label for edit button'),
280
+	 *            'delete' => esc_html__('label for delete button')
281
+	 *            )
282
+	 *        )
283
+	 *
284
+	 * @abstract
285
+	 * @return void
286
+	 */
287
+	abstract protected function _define_page_props();
288
+
289
+
290
+	/**
291
+	 * _set_page_routes
292
+	 * child classes use this to define the page routes for all subpages handled by the class.  Page routes are
293
+	 * assigned to a action => method pairs in an array and to the $_page_routes property.  Each page route must also
294
+	 * have a 'default' route. Here's the format
295
+	 * $this->_page_routes = array(
296
+	 *        'default' => array(
297
+	 *            'func' => '_default_method_handling_route',
298
+	 *            'args' => array('array','of','args'),
299
+	 *            'noheader' => true, //add this in if this page route is processed before any headers are loaded (i.e.
300
+	 *            ajax request, backend processing)
301
+	 *            'headers_sent_route'=>'headers_route_reference', //add this if noheader=>true, and you want to load a
302
+	 *            headers route after.  The string you enter here should match the defined route reference for a
303
+	 *            headers sent route.
304
+	 *            'capability' => 'route_capability', //indicate a string for minimum capability required to access
305
+	 *            this route.
306
+	 *            'obj_id' => 10 // if this route has an object id, then this can include it (used for capability
307
+	 *            checks).
308
+	 *        ),
309
+	 *        'insert_item' => '_method_for_handling_insert_item' //this can be used if all we need to have is a
310
+	 *        handling method.
311
+	 *        )
312
+	 * )
313
+	 *
314
+	 * @abstract
315
+	 * @return void
316
+	 */
317
+	abstract protected function _set_page_routes();
318
+
319
+
320
+	/**
321
+	 * _set_page_config
322
+	 * child classes use this to define the _page_config array for all subpages handled by the class. Each key in the
323
+	 * array corresponds to the page_route for the loaded page. Format:
324
+	 * $this->_page_config = array(
325
+	 *        'default' => array(
326
+	 *            'labels' => array(
327
+	 *                'buttons' => array(
328
+	 *                    'add' => esc_html__('label for adding item'),
329
+	 *                    'edit' => esc_html__('label for editing item'),
330
+	 *                    'delete' => esc_html__('label for deleting item')
331
+	 *                ),
332
+	 *                'publishbox' => esc_html__('Localized Title for Publish metabox', 'event_espresso')
333
+	 *            ), //optional an array of custom labels for various automatically generated elements to use on the
334
+	 *            page. If this isn't present then the defaults will be used as set for the $this->_labels in
335
+	 *            _define_page_props() method
336
+	 *            'nav' => array(
337
+	 *                'label' => esc_html__('Label for Tab', 'event_espresso').
338
+	 *                'url' => 'http://someurl', //automatically generated UNLESS you define
339
+	 *                'css_class' => 'css-class', //automatically generated UNLESS you define
340
+	 *                'order' => 10, //required to indicate tab position.
341
+	 *                'persistent' => false //if you want the nav tab to ONLY display when the specific route is
342
+	 *                displayed then add this parameter.
343
+	 *            'list_table' => 'name_of_list_table' //string for list table class to be loaded for this admin_page.
344
+	 *            'metaboxes' => array('metabox1', 'metabox2'), //if present this key indicates we want to load
345
+	 *            metaboxes set for eventespresso admin pages.
346
+	 *            'has_metaboxes' => true, //this boolean flag can simply be used to indicate if the route will have
347
+	 *            metaboxes.  Typically this is used if the 'metaboxes' index is not used because metaboxes are added
348
+	 *            later.  We just use this flag to make sure the necessary js gets enqueued on page load.
349
+	 *            'has_help_popups' => false //defaults(true) //this boolean flag can simply be used to indicate if the
350
+	 *            given route has help popups setup and if it does then we need to make sure thickbox is enqueued.
351
+	 *            'columns' => array(4, 2), //this key triggers the setup of a page that uses columns (metaboxes).  The
352
+	 *            array indicates the max number of columns (4) and the default number of columns on page load (2).
353
+	 *            There is an option in the "screen_options" dropdown that is setup so users can pick what columns they
354
+	 *            want to display.
355
+	 *            'help_tabs' => array( //this is used for adding help tabs to a page
356
+	 *                'tab_id' => array(
357
+	 *                    'title' => 'tab_title',
358
+	 *                    'filename' => 'name_of_file_containing_content', //this is the primary method for setting
359
+	 *                    help tab content.  The fallback if it isn't present is to try a the callback.  Filename
360
+	 *                    should match a file in the admin folder's "help_tabs" dir (ie..
361
+	 *                    events/help_tabs/name_of_file_containing_content.help_tab.php)
362
+	 *                    'callback' => 'callback_method_for_content', //if 'filename' isn't present then system will
363
+	 *                    attempt to use the callback which should match the name of a method in the class
364
+	 *                    ),
365
+	 *                'tab2_id' => array(
366
+	 *                    'title' => 'tab2 title',
367
+	 *                    'filename' => 'file_name_2'
368
+	 *                    'callback' => 'callback_method_for_content',
369
+	 *                 ),
370
+	 *            'help_sidebar' => 'callback_for_sidebar_content', //this is used for setting up the sidebar in the
371
+	 *            help tab area on an admin page. @link
372
+	 *            http://make.wordpress.org/core/2011/12/06/help-and-screen-api-changes-in-3-3/
373
+	 *            'help_tour' => array(
374
+	 *                'name_of_help_tour_class', //all help tours shoudl be a child class of EE_Help_Tour and located
375
+	 *                in a folder for this admin page named "help_tours", a file name matching the key given here
376
+	 *                (name_of_help_tour_class.class.php), and class matching key given here (name_of_help_tour_class)
377
+	 *            ),
378
+	 *            'require_nonce' => TRUE //this is used if you want to set a route to NOT require a nonce (default is
379
+	 *            true if it isn't present).  To remove the requirement for a nonce check when this route is visited
380
+	 *            just set
381
+	 *            'require_nonce' to FALSE
382
+	 *            )
383
+	 * )
384
+	 *
385
+	 * @abstract
386
+	 * @return void
387
+	 */
388
+	abstract protected function _set_page_config();
389
+
390
+
391
+
392
+
393
+
394
+	/** end sample help_tour methods **/
395
+	/**
396
+	 * _add_screen_options
397
+	 * Child classes can add any extra wp_screen_options within this method using built-in WP functions/methods for
398
+	 * doing so. Note child classes can also define _add_screen_options_($this->_current_view) to limit screen options
399
+	 * to a particular view.
400
+	 *
401
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
402
+	 *         see also WP_Screen object documents...
403
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
404
+	 * @abstract
405
+	 * @return void
406
+	 */
407
+	abstract protected function _add_screen_options();
408
+
409
+
410
+	/**
411
+	 * _add_feature_pointers
412
+	 * Child classes should use this method for implementing any "feature pointers" (using built-in WP styling js).
413
+	 * Note child classes can also define _add_feature_pointers_($this->_current_view) to limit screen options to a
414
+	 * particular view. Note: this is just a placeholder for now.  Implementation will come down the road See:
415
+	 * WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
416
+	 * extended) also see:
417
+	 *
418
+	 * @link   http://eamann.com/tech/wordpress-portland/
419
+	 * @abstract
420
+	 * @return void
421
+	 */
422
+	abstract protected function _add_feature_pointers();
423
+
424
+
425
+	/**
426
+	 * load_scripts_styles
427
+	 * child classes put their wp_enqueue_script and wp_enqueue_style hooks in here for anything they need loaded for
428
+	 * their pages/subpages.  Note this is for all pages/subpages of the system.  You can also load only specific
429
+	 * scripts/styles per view by putting them in a dynamic function in this format
430
+	 * (load_scripts_styles_{$this->_current_view}) which matches your page route (action request arg)
431
+	 *
432
+	 * @abstract
433
+	 * @return void
434
+	 */
435
+	abstract public function load_scripts_styles();
436
+
437
+
438
+	/**
439
+	 * admin_init
440
+	 * Anything that should be set/executed at 'admin_init' WP hook runtime should be put in here.  This will apply to
441
+	 * all pages/views loaded by child class.
442
+	 *
443
+	 * @abstract
444
+	 * @return void
445
+	 */
446
+	abstract public function admin_init();
447
+
448
+
449
+	/**
450
+	 * admin_notices
451
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply to
452
+	 * all pages/views loaded by child class.
453
+	 *
454
+	 * @abstract
455
+	 * @return void
456
+	 */
457
+	abstract public function admin_notices();
458
+
459
+
460
+	/**
461
+	 * admin_footer_scripts
462
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
463
+	 * will apply to all pages/views loaded by child class.
464
+	 *
465
+	 * @return void
466
+	 */
467
+	abstract public function admin_footer_scripts();
468
+
469
+
470
+	/**
471
+	 * admin_footer
472
+	 * anything triggered by the 'admin_footer' WP action hook should be added to here. This particular method will
473
+	 * apply to all pages/views loaded by child class.
474
+	 *
475
+	 * @return void
476
+	 */
477
+	public function admin_footer()
478
+	{
479
+	}
480
+
481
+
482
+	/**
483
+	 * _global_ajax_hooks
484
+	 * all global add_action('wp_ajax_{name_of_hook}') hooks in here.
485
+	 * Note: within the ajax callback methods.
486
+	 *
487
+	 * @abstract
488
+	 * @return void
489
+	 */
490
+	protected function _global_ajax_hooks()
491
+	{
492
+		// for lazy loading of metabox content
493
+		add_action('wp_ajax_espresso-ajax-content', array($this, 'ajax_metabox_content'), 10);
494
+	}
495
+
496
+
497
+	public function ajax_metabox_content()
498
+	{
499
+		$contentid = isset($this->_req_data['contentid']) ? $this->_req_data['contentid'] : '';
500
+		$url = isset($this->_req_data['contenturl']) ? $this->_req_data['contenturl'] : '';
501
+		EE_Admin_Page::cached_rss_display($contentid, $url);
502
+		wp_die();
503
+	}
504
+
505
+
506
+	/**
507
+	 * _page_setup
508
+	 * Makes sure any things that need to be loaded early get handled.  We also escape early here if the page requested
509
+	 * doesn't match the object.
510
+	 *
511
+	 * @final
512
+	 * @return void
513
+	 * @throws EE_Error
514
+	 * @throws InvalidArgumentException
515
+	 * @throws ReflectionException
516
+	 * @throws InvalidDataTypeException
517
+	 * @throws InvalidInterfaceException
518
+	 */
519
+	final protected function _page_setup()
520
+	{
521
+		// requires?
522
+		// admin_init stuff - global - we're setting this REALLY early
523
+		// so if EE_Admin pages have to hook into other WP pages they can.
524
+		// But keep in mind, not everything is available from the EE_Admin Page object at this point.
525
+		add_action('admin_init', array($this, 'admin_init_global'), 5);
526
+		// next verify if we need to load anything...
527
+		$this->_current_page = ! empty($_GET['page']) ? sanitize_key($_GET['page']) : '';
528
+		$this->page_folder = strtolower(
529
+			str_replace(array('_Admin_Page', 'Extend_'), '', get_class($this))
530
+		);
531
+		global $ee_menu_slugs;
532
+		$ee_menu_slugs = (array) $ee_menu_slugs;
533
+		if (! defined('DOING_AJAX') && (! $this->_current_page || ! isset($ee_menu_slugs[ $this->_current_page ]))) {
534
+			return;
535
+		}
536
+		// becuz WP List tables have two duplicate select inputs for choosing bulk actions, we need to copy the action from the second to the first
537
+		if (isset($this->_req_data['action2']) && $this->_req_data['action'] === '-1') {
538
+			$this->_req_data['action'] = ! empty($this->_req_data['action2']) && $this->_req_data['action2'] !== '-1'
539
+				? $this->_req_data['action2']
540
+				: $this->_req_data['action'];
541
+		}
542
+		// then set blank or -1 action values to 'default'
543
+		$this->_req_action = isset($this->_req_data['action'])
544
+							 && ! empty($this->_req_data['action'])
545
+							 && $this->_req_data['action'] !== '-1'
546
+			? sanitize_key($this->_req_data['action'])
547
+			: 'default';
548
+		// if action is 'default' after the above BUT we have  'route' var set, then let's use the route as the action.
549
+		//  This covers cases where we're coming in from a list table that isn't on the default route.
550
+		$this->_req_action = $this->_req_action === 'default' && isset($this->_req_data['route'])
551
+			? $this->_req_data['route'] : $this->_req_action;
552
+		// however if we are doing_ajax and we've got a 'route' set then that's what the req_action will be
553
+		$this->_req_action = defined('DOING_AJAX') && isset($this->_req_data['route'])
554
+			? $this->_req_data['route']
555
+			: $this->_req_action;
556
+		$this->_current_view = $this->_req_action;
557
+		$this->_req_nonce = $this->_req_action . '_nonce';
558
+		$this->_define_page_props();
559
+		$this->_current_page_view_url = add_query_arg(
560
+			array('page' => $this->_current_page, 'action' => $this->_current_view),
561
+			$this->_admin_base_url
562
+		);
563
+		// default things
564
+		$this->_default_espresso_metaboxes = array(
565
+			'_espresso_news_post_box',
566
+			'_espresso_links_post_box',
567
+			'_espresso_ratings_request',
568
+			'_espresso_sponsors_post_box',
569
+		);
570
+		// set page configs
571
+		$this->_set_page_routes();
572
+		$this->_set_page_config();
573
+		// let's include any referrer data in our default_query_args for this route for "stickiness".
574
+		if (isset($this->_req_data['wp_referer'])) {
575
+			$this->_default_route_query_args['wp_referer'] = $this->_req_data['wp_referer'];
576
+		}
577
+		// for caffeinated and other extended functionality.
578
+		//  If there is a _extend_page_config method
579
+		// then let's run that to modify the all the various page configuration arrays
580
+		if (method_exists($this, '_extend_page_config')) {
581
+			$this->_extend_page_config();
582
+		}
583
+		// for CPT and other extended functionality.
584
+		// If there is an _extend_page_config_for_cpt
585
+		// then let's run that to modify all the various page configuration arrays.
586
+		if (method_exists($this, '_extend_page_config_for_cpt')) {
587
+			$this->_extend_page_config_for_cpt();
588
+		}
589
+		// filter routes and page_config so addons can add their stuff. Filtering done per class
590
+		$this->_page_routes = apply_filters(
591
+			'FHEE__' . get_class($this) . '__page_setup__page_routes',
592
+			$this->_page_routes,
593
+			$this
594
+		);
595
+		$this->_page_config = apply_filters(
596
+			'FHEE__' . get_class($this) . '__page_setup__page_config',
597
+			$this->_page_config,
598
+			$this
599
+		);
600
+		// if AHEE__EE_Admin_Page__route_admin_request_$this->_current_view method is present
601
+		// then we call it hooked into the AHEE__EE_Admin_Page__route_admin_request action
602
+		if (method_exists($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view)) {
603
+			add_action(
604
+				'AHEE__EE_Admin_Page__route_admin_request',
605
+				array($this, 'AHEE__EE_Admin_Page__route_admin_request_' . $this->_current_view),
606
+				10,
607
+				2
608
+			);
609
+		}
610
+		// next route only if routing enabled
611
+		if ($this->_routing && ! defined('DOING_AJAX')) {
612
+			$this->_verify_routes();
613
+			// next let's just check user_access and kill if no access
614
+			$this->check_user_access();
615
+			if ($this->_is_UI_request) {
616
+				// admin_init stuff - global, all views for this page class, specific view
617
+				add_action('admin_init', array($this, 'admin_init'), 10);
618
+				if (method_exists($this, 'admin_init_' . $this->_current_view)) {
619
+					add_action('admin_init', array($this, 'admin_init_' . $this->_current_view), 15);
620
+				}
621
+			} else {
622
+				// hijack regular WP loading and route admin request immediately
623
+				@ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
624
+				$this->route_admin_request();
625
+			}
626
+		}
627
+	}
628
+
629
+
630
+	/**
631
+	 * Provides a way for related child admin pages to load stuff on the loaded admin page.
632
+	 *
633
+	 * @return void
634
+	 * @throws EE_Error
635
+	 */
636
+	private function _do_other_page_hooks()
637
+	{
638
+		$registered_pages = apply_filters('FHEE_do_other_page_hooks_' . $this->page_slug, array());
639
+		foreach ($registered_pages as $page) {
640
+			// now let's setup the file name and class that should be present
641
+			$classname = str_replace('.class.php', '', $page);
642
+			// autoloaders should take care of loading file
643
+			if (! class_exists($classname)) {
644
+				$error_msg[] = sprintf(
645
+					esc_html__(
646
+						'Something went wrong with loading the %s admin hooks page.',
647
+						'event_espresso'
648
+					),
649
+					$page
650
+				);
651
+				$error_msg[] = $error_msg[0]
652
+							   . "\r\n"
653
+							   . sprintf(
654
+								   esc_html__(
655
+									   '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',
656
+									   'event_espresso'
657
+								   ),
658
+								   $page,
659
+								   '<br />',
660
+								   '<strong>' . $classname . '</strong>'
661
+							   );
662
+				throw new EE_Error(implode('||', $error_msg));
663
+			}
664
+			// // notice we are passing the instance of this class to the hook object.
665
+			$this->loader->getShared($classname, [$this]);
666
+		}
667
+	}
668
+
669
+
670
+	/**
671
+	 * @throws DomainException
672
+	 * @throws EE_Error
673
+	 * @throws InvalidArgumentException
674
+	 * @throws InvalidDataTypeException
675
+	 * @throws InvalidInterfaceException
676
+	 * @throws ReflectionException
677
+	 * @since $VID:$
678
+	 */
679
+	public function load_page_dependencies()
680
+	{
681
+		try {
682
+			$this->_load_page_dependencies();
683
+		} catch (EE_Error $e) {
684
+			$e->get_error();
685
+		}
686
+	}
687
+
688
+
689
+	/**
690
+	 * load_page_dependencies
691
+	 * loads things specific to this page class when its loaded.  Really helps with efficiency.
692
+	 *
693
+	 * @return void
694
+	 * @throws DomainException
695
+	 * @throws EE_Error
696
+	 * @throws InvalidArgumentException
697
+	 * @throws InvalidDataTypeException
698
+	 * @throws InvalidInterfaceException
699
+	 * @throws ReflectionException
700
+	 */
701
+	protected function _load_page_dependencies()
702
+	{
703
+		// let's set the current_screen and screen options to override what WP set
704
+		$this->_current_screen = get_current_screen();
705
+		// load admin_notices - global, page class, and view specific
706
+		add_action('admin_notices', array($this, 'admin_notices_global'), 5);
707
+		add_action('admin_notices', array($this, 'admin_notices'), 10);
708
+		if (method_exists($this, 'admin_notices_' . $this->_current_view)) {
709
+			add_action('admin_notices', array($this, 'admin_notices_' . $this->_current_view), 15);
710
+		}
711
+		// load network admin_notices - global, page class, and view specific
712
+		add_action('network_admin_notices', array($this, 'network_admin_notices_global'), 5);
713
+		if (method_exists($this, 'network_admin_notices_' . $this->_current_view)) {
714
+			add_action('network_admin_notices', array($this, 'network_admin_notices_' . $this->_current_view));
715
+		}
716
+		// this will save any per_page screen options if they are present
717
+		$this->_set_per_page_screen_options();
718
+		// setup list table properties
719
+		$this->_set_list_table();
720
+		// child classes can "register" a metabox to be automatically handled via the _page_config array property.
721
+		// However in some cases the metaboxes will need to be added within a route handling callback.
722
+		$this->_add_registered_meta_boxes();
723
+		$this->_add_screen_columns();
724
+		// add screen options - global, page child class, and view specific
725
+		$this->_add_global_screen_options();
726
+		$this->_add_screen_options();
727
+		$add_screen_options = "_add_screen_options_{$this->_current_view}";
728
+		if (method_exists($this, $add_screen_options)) {
729
+			$this->{$add_screen_options}();
730
+		}
731
+		// add help tab(s) and tours- set via page_config and qtips.
732
+		$this->_add_help_tour();
733
+		$this->_add_help_tabs();
734
+		$this->_add_qtips();
735
+		// add feature_pointers - global, page child class, and view specific
736
+		$this->_add_feature_pointers();
737
+		$this->_add_global_feature_pointers();
738
+		$add_feature_pointer = "_add_feature_pointer_{$this->_current_view}";
739
+		if (method_exists($this, $add_feature_pointer)) {
740
+			$this->{$add_feature_pointer}();
741
+		}
742
+		// enqueue scripts/styles - global, page class, and view specific
743
+		add_action('admin_enqueue_scripts', array($this, 'load_global_scripts_styles'), 5);
744
+		add_action('admin_enqueue_scripts', array($this, 'load_scripts_styles'), 10);
745
+		if (method_exists($this, "load_scripts_styles_{$this->_current_view}")) {
746
+			add_action('admin_enqueue_scripts', array($this, "load_scripts_styles_{$this->_current_view}"), 15);
747
+		}
748
+		add_action('admin_enqueue_scripts', array($this, 'admin_footer_scripts_eei18n_js_strings'), 100);
749
+		// admin_print_footer_scripts - global, page child class, and view specific.
750
+		// NOTE, despite the name, whenever possible, scripts should NOT be loaded using this.
751
+		// In most cases that's doing_it_wrong().  But adding hidden container elements etc.
752
+		// is a good use case. Notice the late priority we're giving these
753
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts_global'), 99);
754
+		add_action('admin_print_footer_scripts', array($this, 'admin_footer_scripts'), 100);
755
+		if (method_exists($this, "admin_footer_scripts_{$this->_current_view}")) {
756
+			add_action('admin_print_footer_scripts', array($this, "admin_footer_scripts_{$this->_current_view}"), 101);
757
+		}
758
+		// admin footer scripts
759
+		add_action('admin_footer', array($this, 'admin_footer_global'), 99);
760
+		add_action('admin_footer', array($this, 'admin_footer'), 100);
761
+		if (method_exists($this, "admin_footer_{$this->_current_view}")) {
762
+			add_action('admin_footer', array($this, "admin_footer_{$this->_current_view}"), 101);
763
+		}
764
+		do_action('FHEE__EE_Admin_Page___load_page_dependencies__after_load', $this->page_slug);
765
+		// targeted hook
766
+		do_action(
767
+			"FHEE__EE_Admin_Page___load_page_dependencies__after_load__{$this->page_slug}__{$this->_req_action}"
768
+		);
769
+	}
770
+
771
+
772
+	/**
773
+	 * _set_defaults
774
+	 * This sets some global defaults for class properties.
775
+	 */
776
+	private function _set_defaults()
777
+	{
778
+		$this->_current_screen = $this->_admin_page_title = $this->_req_action = $this->_req_nonce = null;
779
+		$this->_event = $this->_template_path = $this->_column_template_path = null;
780
+		$this->_nav_tabs = $this->_views = $this->_page_routes = array();
781
+		$this->_page_config = $this->_default_route_query_args = array();
782
+		$this->_default_nav_tab_name = 'overview';
783
+		// init template args
784
+		$this->_template_args = array(
785
+			'admin_page_header'  => '',
786
+			'admin_page_content' => '',
787
+			'post_body_content'  => '',
788
+			'before_list_table'  => '',
789
+			'after_list_table'   => '',
790
+		);
791
+	}
792
+
793
+
794
+	/**
795
+	 * route_admin_request
796
+	 *
797
+	 * @see    _route_admin_request()
798
+	 * @return exception|void error
799
+	 * @throws InvalidArgumentException
800
+	 * @throws InvalidInterfaceException
801
+	 * @throws InvalidDataTypeException
802
+	 * @throws EE_Error
803
+	 * @throws ReflectionException
804
+	 */
805
+	public function route_admin_request()
806
+	{
807
+		try {
808
+			$this->_route_admin_request();
809
+		} catch (EE_Error $e) {
810
+			$e->get_error();
811
+		}
812
+	}
813
+
814
+
815
+	public function set_wp_page_slug($wp_page_slug)
816
+	{
817
+		$this->_wp_page_slug = $wp_page_slug;
818
+		// if in network admin then we need to append "-network" to the page slug. Why? Because that's how WP rolls...
819
+		if (is_network_admin()) {
820
+			$this->_wp_page_slug .= '-network';
821
+		}
822
+	}
823
+
824
+
825
+	/**
826
+	 * _verify_routes
827
+	 * All this method does is verify the incoming request and make sure that routes exist for it.  We do this early so
828
+	 * we know if we need to drop out.
829
+	 *
830
+	 * @return bool
831
+	 * @throws EE_Error
832
+	 */
833
+	protected function _verify_routes()
834
+	{
835
+		if (! $this->_current_page && ! defined('DOING_AJAX')) {
836
+			return false;
837
+		}
838
+		$this->_route = false;
839
+		// check that the page_routes array is not empty
840
+		if (empty($this->_page_routes)) {
841
+			// user error msg
842
+			$error_msg = sprintf(
843
+				esc_html__('No page routes have been set for the %s admin page.', 'event_espresso'),
844
+				$this->_admin_page_title
845
+			);
846
+			// developer error msg
847
+			$error_msg .= '||' . $error_msg
848
+						  . esc_html__(
849
+							  ' Make sure the "set_page_routes()" method exists, and is setting the "_page_routes" array properly.',
850
+							  'event_espresso'
851
+						  );
852
+			throw new EE_Error($error_msg);
853
+		}
854
+		// and that the requested page route exists
855
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
856
+			$this->_route = $this->_page_routes[ $this->_req_action ];
857
+			$this->_route_config = isset($this->_page_config[ $this->_req_action ])
858
+				? $this->_page_config[ $this->_req_action ] : array();
859
+		} else {
860
+			// user error msg
861
+			$error_msg = sprintf(
862
+				esc_html__(
863
+					'The requested page route does not exist for the %s admin page.',
864
+					'event_espresso'
865
+				),
866
+				$this->_admin_page_title
867
+			);
868
+			// developer error msg
869
+			$error_msg .= '||' . $error_msg
870
+						  . sprintf(
871
+							  esc_html__(
872
+								  ' Create a key in the "_page_routes" array named "%s" and set its value to the appropriate method.',
873
+								  'event_espresso'
874
+							  ),
875
+							  $this->_req_action
876
+						  );
877
+			throw new EE_Error($error_msg);
878
+		}
879
+		// and that a default route exists
880
+		if (! array_key_exists('default', $this->_page_routes)) {
881
+			// user error msg
882
+			$error_msg = sprintf(
883
+				esc_html__(
884
+					'A default page route has not been set for the % admin page.',
885
+					'event_espresso'
886
+				),
887
+				$this->_admin_page_title
888
+			);
889
+			// developer error msg
890
+			$error_msg .= '||' . $error_msg
891
+						  . esc_html__(
892
+							  ' Create a key in the "_page_routes" array named "default" and set its value to your default page method.',
893
+							  'event_espresso'
894
+						  );
895
+			throw new EE_Error($error_msg);
896
+		}
897
+
898
+		// first lets' catch if the UI request has EVER been set.
899
+		if ($this->_is_UI_request === null) {
900
+			// lets set if this is a UI request or not.
901
+			$this->_is_UI_request = ! isset($this->_req_data['noheader']) || $this->_req_data['noheader'] !== true;
902
+			// wait a minute... we might have a noheader in the route array
903
+			$this->_is_UI_request = is_array($this->_route)
904
+									&& isset($this->_route['noheader'])
905
+									&& $this->_route['noheader'] ? false : $this->_is_UI_request;
906
+		}
907
+		$this->_set_current_labels();
908
+		return true;
909
+	}
910
+
911
+
912
+	/**
913
+	 * this method simply verifies a given route and makes sure its an actual route available for the loaded page
914
+	 *
915
+	 * @param  string $route the route name we're verifying
916
+	 * @return mixed (bool|Exception)      we'll throw an exception if this isn't a valid route.
917
+	 * @throws EE_Error
918
+	 */
919
+	protected function _verify_route($route)
920
+	{
921
+		if (array_key_exists($this->_req_action, $this->_page_routes)) {
922
+			return true;
923
+		}
924
+		// user error msg
925
+		$error_msg = sprintf(
926
+			esc_html__('The given page route does not exist for the %s admin page.', 'event_espresso'),
927
+			$this->_admin_page_title
928
+		);
929
+		// developer error msg
930
+		$error_msg .= '||' . $error_msg
931
+					  . sprintf(
932
+						  esc_html__(
933
+							  ' Check the route you are using in your method (%s) and make sure it matches a route set in your "_page_routes" array property',
934
+							  'event_espresso'
935
+						  ),
936
+						  $route
937
+					  );
938
+		throw new EE_Error($error_msg);
939
+	}
940
+
941
+
942
+	/**
943
+	 * perform nonce verification
944
+	 * This method has be encapsulated here so that any ajax requests that bypass normal routes can verify their nonces
945
+	 * using this method (and save retyping!)
946
+	 *
947
+	 * @param string $nonce     The nonce sent
948
+	 * @param string $nonce_ref The nonce reference string (name0)
949
+	 * @return void
950
+	 * @throws EE_Error
951
+	 * @throws InvalidArgumentException
952
+	 * @throws InvalidDataTypeException
953
+	 * @throws InvalidInterfaceException
954
+	 */
955
+	protected function _verify_nonce($nonce, $nonce_ref)
956
+	{
957
+		// verify nonce against expected value
958
+		if (! wp_verify_nonce($nonce, $nonce_ref)) {
959
+			// these are not the droids you are looking for !!!
960
+			$msg = sprintf(
961
+				esc_html__('%sNonce Fail.%s', 'event_espresso'),
962
+				'<a href="http://www.youtube.com/watch?v=56_S0WeTkzs">',
963
+				'</a>'
964
+			);
965
+			if (WP_DEBUG) {
966
+				$msg .= "\n  "
967
+						. sprintf(
968
+							esc_html__(
969
+								'In order to dynamically generate nonces for your actions, use the %s::add_query_args_and_nonce() method. May the Nonce be with you!',
970
+								'event_espresso'
971
+							),
972
+							EE_Admin_Page::class
973
+						);
974
+			}
975
+			if (! defined('DOING_AJAX')) {
976
+				wp_die($msg);
977
+			} else {
978
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
979
+				$this->_return_json();
980
+			}
981
+		}
982
+	}
983
+
984
+
985
+	/**
986
+	 * _route_admin_request()
987
+	 * Meat and potatoes of the class.  Basically, this dude checks out what's being requested and sees if there are
988
+	 * some doodads to work the magic and handle the flingjangy. Translation:  Checks if the requested action is listed
989
+	 * in the page routes and then will try to load the corresponding method.
990
+	 *
991
+	 * @return void
992
+	 * @throws EE_Error
993
+	 * @throws InvalidArgumentException
994
+	 * @throws InvalidDataTypeException
995
+	 * @throws InvalidInterfaceException
996
+	 * @throws ReflectionException
997
+	 */
998
+	protected function _route_admin_request()
999
+	{
1000
+		if (! $this->_is_UI_request) {
1001
+			$this->_verify_routes();
1002
+		}
1003
+		$nonce_check = isset($this->_route_config['require_nonce'])
1004
+			? $this->_route_config['require_nonce']
1005
+			: true;
1006
+		if ($this->_req_action !== 'default' && $nonce_check) {
1007
+			// set nonce from post data
1008
+			$nonce = isset($this->_req_data[ $this->_req_nonce ])
1009
+				? sanitize_text_field($this->_req_data[ $this->_req_nonce ])
1010
+				: '';
1011
+			$this->_verify_nonce($nonce, $this->_req_nonce);
1012
+		}
1013
+		// set the nav_tabs array but ONLY if this is  UI_request
1014
+		if ($this->_is_UI_request) {
1015
+			$this->_set_nav_tabs();
1016
+		}
1017
+		// grab callback function
1018
+		$func = is_array($this->_route) && isset($this->_route['func']) ? $this->_route['func'] : $this->_route;
1019
+		// check if callback has args
1020
+		$args = is_array($this->_route) && isset($this->_route['args']) ? $this->_route['args'] : array();
1021
+		$error_msg = '';
1022
+		// action right before calling route
1023
+		// (hook is something like 'AHEE__Registrations_Admin_Page__route_admin_request')
1024
+		if (! did_action('AHEE__EE_Admin_Page__route_admin_request')) {
1025
+			do_action('AHEE__EE_Admin_Page__route_admin_request', $this->_current_view, $this);
1026
+		}
1027
+		// right before calling the route, let's remove _wp_http_referer from the
1028
+		// $_SERVER[REQUEST_URI] global (its now in _req_data for route processing).
1029
+		$_SERVER['REQUEST_URI'] = remove_query_arg(
1030
+			'_wp_http_referer',
1031
+			wp_unslash($_SERVER['REQUEST_URI'])
1032
+		);
1033
+		if (! empty($func)) {
1034
+			if (is_array($func)) {
1035
+				list($class, $method) = $func;
1036
+			} elseif (strpos($func, '::') !== false) {
1037
+				list($class, $method) = explode('::', $func);
1038
+			} else {
1039
+				$class = $this;
1040
+				$method = $func;
1041
+			}
1042
+			if (! (is_object($class) && $class === $this)) {
1043
+				// send along this admin page object for access by addons.
1044
+				$args['admin_page_object'] = $this;
1045
+			}
1046
+			// is it a method on a class that doesn't work?
1047
+			if (((method_exists($class, $method)
1048
+				  && call_user_func_array(array($class, $method), $args) === false)
1049
+				 && (// is it a standalone function that doesn't work?
1050
+					 function_exists($method)
1051
+					 && call_user_func_array(
1052
+						 $func,
1053
+						 array_merge(array('admin_page_object' => $this), $args)
1054
+					 ) === false
1055
+				 )) || (// is it neither a class method NOR a standalone function?
1056
+					! function_exists($method)
1057
+					&& ! method_exists($class, $method)
1058
+				)
1059
+			) {
1060
+				// user error msg
1061
+				$error_msg = esc_html__(
1062
+					'An error occurred. The  requested page route could not be found.',
1063
+					'event_espresso'
1064
+				);
1065
+				// developer error msg
1066
+				$error_msg .= '||';
1067
+				$error_msg .= sprintf(
1068
+					esc_html__(
1069
+						'Page route "%s" could not be called. Check that the spelling for method names and actions in the "_page_routes" array are all correct.',
1070
+						'event_espresso'
1071
+					),
1072
+					$method
1073
+				);
1074
+			}
1075
+			if (! empty($error_msg)) {
1076
+				throw new EE_Error($error_msg);
1077
+			}
1078
+		}
1079
+		// if we've routed and this route has a no headers route AND a sent_headers_route,
1080
+		// then we need to reset the routing properties to the new route.
1081
+		// 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.
1082
+		if ($this->_is_UI_request === false
1083
+			&& is_array($this->_route)
1084
+			&& ! empty($this->_route['headers_sent_route'])
1085
+		) {
1086
+			$this->_reset_routing_properties($this->_route['headers_sent_route']);
1087
+		}
1088
+	}
1089
+
1090
+
1091
+	/**
1092
+	 * This method just allows the resetting of page properties in the case where a no headers
1093
+	 * route redirects to a headers route in its route config.
1094
+	 *
1095
+	 * @since   4.3.0
1096
+	 * @param  string $new_route New (non header) route to redirect to.
1097
+	 * @return   void
1098
+	 * @throws ReflectionException
1099
+	 * @throws InvalidArgumentException
1100
+	 * @throws InvalidInterfaceException
1101
+	 * @throws InvalidDataTypeException
1102
+	 * @throws EE_Error
1103
+	 */
1104
+	protected function _reset_routing_properties($new_route)
1105
+	{
1106
+		$this->_is_UI_request = true;
1107
+		// now we set the current route to whatever the headers_sent_route is set at
1108
+		$this->_req_data['action'] = $new_route;
1109
+		// rerun page setup
1110
+		$this->_page_setup();
1111
+	}
1112
+
1113
+
1114
+	/**
1115
+	 * _add_query_arg
1116
+	 * adds nonce to array of arguments then calls WP add_query_arg function
1117
+	 *(internally just uses EEH_URL's function with the same name)
1118
+	 *
1119
+	 * @param array  $args
1120
+	 * @param string $url
1121
+	 * @param bool   $sticky                  if true, then the existing Request params will be appended to the
1122
+	 *                                        generated url in an associative array indexed by the key 'wp_referer';
1123
+	 *                                        Example usage: If the current page is:
1124
+	 *                                        http://mydomain.com/wp-admin/admin.php?page=espresso_registrations
1125
+	 *                                        &action=default&event_id=20&month_range=March%202015
1126
+	 *                                        &_wpnonce=5467821
1127
+	 *                                        and you call:
1128
+	 *                                        EE_Admin_Page::add_query_args_and_nonce(
1129
+	 *                                        array(
1130
+	 *                                        'action' => 'resend_something',
1131
+	 *                                        'page=>espresso_registrations'
1132
+	 *                                        ),
1133
+	 *                                        $some_url,
1134
+	 *                                        true
1135
+	 *                                        );
1136
+	 *                                        It will produce a url in this structure:
1137
+	 *                                        http://{$some_url}/?page=espresso_registrations&action=resend_something
1138
+	 *                                        &wp_referer[action]=default&wp_referer[event_id]=20&wpreferer[
1139
+	 *                                        month_range]=March%202015
1140
+	 * @param   bool $exclude_nonce           If true, the the nonce will be excluded from the generated nonce.
1141
+	 * @return string
1142
+	 */
1143
+	public static function add_query_args_and_nonce(
1144
+		$args = array(),
1145
+		$url = '',
1146
+		$sticky = false,
1147
+		$exclude_nonce = false
1148
+	) {
1149
+		// if there is a _wp_http_referer include the values from the request but only if sticky = true
1150
+		if ($sticky) {
1151
+			$request = $_REQUEST;
1152
+			unset($request['_wp_http_referer'], $request['wp_referer']);
1153
+			foreach ($request as $key => $value) {
1154
+				// do not add nonces
1155
+				if (strpos($key, 'nonce') !== false) {
1156
+					continue;
1157
+				}
1158
+				$args[ 'wp_referer[' . $key . ']' ] = $value;
1159
+			}
1160
+		}
1161
+		return EEH_URL::add_query_args_and_nonce($args, $url, $exclude_nonce);
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * This returns a generated link that will load the related help tab.
1167
+	 *
1168
+	 * @param  string $help_tab_id the id for the connected help tab
1169
+	 * @param  string $icon_style  (optional) include css class for the style you want to use for the help icon.
1170
+	 * @param  string $help_text   (optional) send help text you want to use for the link if default not to be used
1171
+	 * @uses EEH_Template::get_help_tab_link()
1172
+	 * @return string              generated link
1173
+	 */
1174
+	protected function _get_help_tab_link($help_tab_id, $icon_style = '', $help_text = '')
1175
+	{
1176
+		return EEH_Template::get_help_tab_link(
1177
+			$help_tab_id,
1178
+			$this->page_slug,
1179
+			$this->_req_action,
1180
+			$icon_style,
1181
+			$help_text
1182
+		);
1183
+	}
1184
+
1185
+
1186
+	/**
1187
+	 * _add_help_tabs
1188
+	 * Note child classes define their help tabs within the page_config array.
1189
+	 *
1190
+	 * @link   http://codex.wordpress.org/Function_Reference/add_help_tab
1191
+	 * @return void
1192
+	 * @throws DomainException
1193
+	 * @throws EE_Error
1194
+	 * @throws ReflectionException
1195
+	 */
1196
+	protected function _add_help_tabs()
1197
+	{
1198
+		$tour_buttons = '';
1199
+		if (isset($this->_page_config[ $this->_req_action ])) {
1200
+			$config = $this->_page_config[ $this->_req_action ];
1201
+			// is there a help tour for the current route?  if there is let's setup the tour buttons
1202
+			if (isset($this->_help_tour[ $this->_req_action ])) {
1203
+				$tb = array();
1204
+				$tour_buttons = '<div class="ee-abs-container"><div class="ee-help-tour-restart-buttons">';
1205
+				foreach ($this->_help_tour['tours'] as $tour) {
1206
+					// if this is the end tour then we don't need to setup a button
1207
+					if ($tour instanceof EE_Help_Tour_final_stop || ! $tour instanceof EE_Help_Tour) {
1208
+						continue;
1209
+					}
1210
+					$tb[] = '<button id="trigger-tour-'
1211
+							. $tour->get_slug()
1212
+							. '" class="button-primary trigger-ee-help-tour">'
1213
+							. $tour->get_label()
1214
+							. '</button>';
1215
+				}
1216
+				$tour_buttons .= implode('<br />', $tb);
1217
+				$tour_buttons .= '</div></div>';
1218
+			}
1219
+			// let's see if there is a help_sidebar set for the current route and we'll set that up for usage as well.
1220
+			if (is_array($config) && isset($config['help_sidebar'])) {
1221
+				// check that the callback given is valid
1222
+				if (! method_exists($this, $config['help_sidebar'])) {
1223
+					throw new EE_Error(
1224
+						sprintf(
1225
+							esc_html__(
1226
+								'The _page_config array has a callback set for the "help_sidebar" option.  However the callback given (%s) is not a valid callback.  Doublecheck the spelling and make sure this method exists for the class %s',
1227
+								'event_espresso'
1228
+							),
1229
+							$config['help_sidebar'],
1230
+							get_class($this)
1231
+						)
1232
+					);
1233
+				}
1234
+				$content = apply_filters(
1235
+					'FHEE__' . get_class($this) . '__add_help_tabs__help_sidebar',
1236
+					$this->{$config['help_sidebar']}()
1237
+				);
1238
+				$content .= $tour_buttons; // add help tour buttons.
1239
+				// do we have any help tours setup?  Cause if we do we want to add the buttons
1240
+				$this->_current_screen->set_help_sidebar($content);
1241
+			}
1242
+			// if there ARE tour buttons...
1243
+			if (! empty($tour_buttons)) {
1244
+				// if we DON'T have config help sidebar then we'll just add the tour buttons to the sidebar.
1245
+				if (! isset($config['help_sidebar'])) {
1246
+					$this->_current_screen->set_help_sidebar($tour_buttons);
1247
+				}
1248
+				// handle if no help_tabs are set so the sidebar will still show for the help tour buttons
1249
+				if (! isset($config['help_tabs'])) {
1250
+					$_ht['id'] = $this->page_slug;
1251
+					$_ht['title'] = esc_html__('Help Tours', 'event_espresso');
1252
+					$_ht['content'] = '<p>'
1253
+									  . esc_html__(
1254
+										  'The buttons to the right allow you to start/restart any help tours available for this page',
1255
+										  'event_espresso'
1256
+									  ) . '</p>';
1257
+					$this->_current_screen->add_help_tab($_ht);
1258
+				}
1259
+			}
1260
+			if (! isset($config['help_tabs'])) {
1261
+				return;
1262
+			} //no help tabs for this route
1263
+			foreach ((array) $config['help_tabs'] as $tab_id => $cfg) {
1264
+				// we're here so there ARE help tabs!
1265
+				// make sure we've got what we need
1266
+				if (! isset($cfg['title'])) {
1267
+					throw new EE_Error(
1268
+						esc_html__(
1269
+							'The _page_config array is not set up properly for help tabs.  It is missing a title',
1270
+							'event_espresso'
1271
+						)
1272
+					);
1273
+				}
1274
+				if (! isset($cfg['filename']) && ! isset($cfg['callback']) && ! isset($cfg['content'])) {
1275
+					throw new EE_Error(
1276
+						esc_html__(
1277
+							'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',
1278
+							'event_espresso'
1279
+						)
1280
+					);
1281
+				}
1282
+				// first priority goes to content.
1283
+				if (! empty($cfg['content'])) {
1284
+					$content = ! empty($cfg['content']) ? $cfg['content'] : null;
1285
+					// second priority goes to filename
1286
+				} elseif (! empty($cfg['filename'])) {
1287
+					$file_path = $this->_get_dir() . '/help_tabs/' . $cfg['filename'] . '.help_tab.php';
1288
+					// 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)
1289
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1290
+															 . basename($this->_get_dir())
1291
+															 . '/help_tabs/'
1292
+															 . $cfg['filename']
1293
+															 . '.help_tab.php' : $file_path;
1294
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1295
+					if (! isset($cfg['callback']) && ! is_readable($file_path)) {
1296
+						EE_Error::add_error(
1297
+							sprintf(
1298
+								esc_html__(
1299
+									'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',
1300
+									'event_espresso'
1301
+								),
1302
+								$tab_id,
1303
+								key($config),
1304
+								$file_path
1305
+							),
1306
+							__FILE__,
1307
+							__FUNCTION__,
1308
+							__LINE__
1309
+						);
1310
+						return;
1311
+					}
1312
+					$template_args['admin_page_obj'] = $this;
1313
+					$content = EEH_Template::display_template(
1314
+						$file_path,
1315
+						$template_args,
1316
+						true
1317
+					);
1318
+				} else {
1319
+					$content = '';
1320
+				}
1321
+				// check if callback is valid
1322
+				if (empty($content) && (
1323
+						! isset($cfg['callback']) || ! method_exists($this, $cfg['callback'])
1324
+					)
1325
+				) {
1326
+					EE_Error::add_error(
1327
+						sprintf(
1328
+							esc_html__(
1329
+								'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.',
1330
+								'event_espresso'
1331
+							),
1332
+							$cfg['title']
1333
+						),
1334
+						__FILE__,
1335
+						__FUNCTION__,
1336
+						__LINE__
1337
+					);
1338
+					return;
1339
+				}
1340
+				// setup config array for help tab method
1341
+				$id = $this->page_slug . '-' . $this->_req_action . '-' . $tab_id;
1342
+				$_ht = array(
1343
+					'id'       => $id,
1344
+					'title'    => $cfg['title'],
1345
+					'callback' => isset($cfg['callback']) && empty($content) ? array($this, $cfg['callback']) : null,
1346
+					'content'  => $content,
1347
+				);
1348
+				$this->_current_screen->add_help_tab($_ht);
1349
+			}
1350
+		}
1351
+	}
1352
+
1353
+
1354
+	/**
1355
+	 * This basically checks loaded $_page_config property to see if there are any help_tours defined.  "help_tours" is
1356
+	 * an array with properties for setting up usage of the joyride plugin
1357
+	 *
1358
+	 * @link   http://zurb.com/playground/jquery-joyride-feature-tour-plugin
1359
+	 * @see    instructions regarding the format and construction of the "help_tour" array element is found in the
1360
+	 *         _set_page_config() comments
1361
+	 * @return void
1362
+	 * @throws EE_Error
1363
+	 * @throws InvalidArgumentException
1364
+	 * @throws InvalidDataTypeException
1365
+	 * @throws InvalidInterfaceException
1366
+	 * @throws ReflectionException
1367
+	 */
1368
+	protected function _add_help_tour()
1369
+	{
1370
+		$tours = array();
1371
+		$this->_help_tour = array();
1372
+		// exit early if help tours are turned off globally
1373
+		if ((defined('EE_DISABLE_HELP_TOURS') && EE_DISABLE_HELP_TOURS)
1374
+			|| ! EE_Registry::instance()->CFG->admin->help_tour_activation
1375
+		) {
1376
+			return;
1377
+		}
1378
+		// loop through _page_config to find any help_tour defined
1379
+		foreach ($this->_page_config as $route => $config) {
1380
+			// we're only going to set things up for this route
1381
+			if ($route !== $this->_req_action) {
1382
+				continue;
1383
+			}
1384
+			if (isset($config['help_tour'])) {
1385
+				foreach ($config['help_tour'] as $tour) {
1386
+					$file_path = $this->_get_dir() . '/help_tours/' . $tour . '.class.php';
1387
+					// let's see if we can get that file...
1388
+					// if not its possible this is a decaf route not set in caffeinated
1389
+					// so lets try and get the caffeinated equivalent
1390
+					$file_path = ! is_readable($file_path) ? EE_ADMIN_PAGES
1391
+															 . basename($this->_get_dir())
1392
+															 . '/help_tours/'
1393
+															 . $tour
1394
+															 . '.class.php' : $file_path;
1395
+					// if file is STILL not readable then let's do a EE_Error so its more graceful than a fatal error.
1396
+					if (! is_readable($file_path)) {
1397
+						EE_Error::add_error(
1398
+							sprintf(
1399
+								esc_html__(
1400
+									'The file path given for the help tour (%s) is not a valid path.  Please check that the string you set for the help tour on this route (%s) is the correct spelling',
1401
+									'event_espresso'
1402
+								),
1403
+								$file_path,
1404
+								$tour
1405
+							),
1406
+							__FILE__,
1407
+							__FUNCTION__,
1408
+							__LINE__
1409
+						);
1410
+						return;
1411
+					}
1412
+					require_once $file_path;
1413
+					if (! class_exists($tour)) {
1414
+						$error_msg = [];
1415
+						$error_msg[] = sprintf(
1416
+							esc_html__('Something went wrong with loading the %s Help Tour Class.', 'event_espresso'),
1417
+							$tour
1418
+						);
1419
+						$error_msg[] = $error_msg[0] . "\r\n"
1420
+									   . sprintf(
1421
+										   esc_html__(
1422
+											   'There is no class in place for the %s help tour.%s Make sure you have <strong>%s</strong> defined in the "help_tour" array for the %s route of the % admin page.',
1423
+											   'event_espresso'
1424
+										   ),
1425
+										   $tour,
1426
+										   '<br />',
1427
+										   $tour,
1428
+										   $this->_req_action,
1429
+										   get_class($this)
1430
+									   );
1431
+						throw new EE_Error(implode('||', $error_msg));
1432
+					}
1433
+					$tour_obj = new $tour($this->_is_caf);
1434
+					$tours[] = $tour_obj;
1435
+					$this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($tour_obj);
1436
+				}
1437
+				// let's inject the end tour stop element common to all pages... this will only get seen once per machine.
1438
+				$end_stop_tour = new EE_Help_Tour_final_stop($this->_is_caf);
1439
+				$tours[] = $end_stop_tour;
1440
+				$this->_help_tour[ $route ][] = EEH_Template::help_tour_stops_generator($end_stop_tour);
1441
+			}
1442
+		}
1443
+
1444
+		if (! empty($tours)) {
1445
+			$this->_help_tour['tours'] = $tours;
1446
+		}
1447
+		// that's it!  Now that the $_help_tours property is set (or not)
1448
+		// the scripts and html should be taken care of automatically.
1449
+
1450
+		/**
1451
+		 * Allow extending the help tours variable.
1452
+		 *
1453
+		 * @param array $_help_tour The array containing all help tour information to be displayed.
1454
+		 */
1455
+		$this->_help_tour = apply_filters('FHEE__EE_Admin_Page___add_help_tour___help_tour', $this->_help_tour);
1456
+	}
1457
+
1458
+
1459
+	/**
1460
+	 * This simply sets up any qtips that have been defined in the page config
1461
+	 *
1462
+	 * @return void
1463
+	 * @throws ReflectionException
1464
+	 * @throws EE_Error
1465
+	 */
1466
+	protected function _add_qtips()
1467
+	{
1468
+		if (isset($this->_route_config['qtips'])) {
1469
+			$qtips = (array) $this->_route_config['qtips'];
1470
+			// load qtip loader
1471
+			$path = array(
1472
+				$this->_get_dir() . '/qtips/',
1473
+				EE_ADMIN_PAGES . basename($this->_get_dir()) . '/qtips/',
1474
+			);
1475
+			$qtip_loader = EEH_Qtip_Loader::instance();
1476
+			if ($qtip_loader instanceof EEH_Qtip_Loader) {
1477
+				$qtip_loader->register($qtips, $path);
1478
+			}
1479
+		}
1480
+	}
1481
+
1482
+
1483
+	/**
1484
+	 * _set_nav_tabs
1485
+	 * This sets up the nav tabs from the page_routes array.  This method can be overwritten by child classes if you
1486
+	 * wish to add additional tabs or modify accordingly.
1487
+	 *
1488
+	 * @return void
1489
+	 * @throws InvalidArgumentException
1490
+	 * @throws InvalidInterfaceException
1491
+	 * @throws InvalidDataTypeException
1492
+	 */
1493
+	protected function _set_nav_tabs()
1494
+	{
1495
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1496
+		$i = 0;
1497
+		foreach ($this->_page_config as $slug => $config) {
1498
+			if (! is_array($config)
1499
+				|| (
1500
+					is_array($config)
1501
+					&& (
1502
+						(isset($config['nav']) && ! $config['nav'])
1503
+						|| ! isset($config['nav'])
1504
+					)
1505
+				)
1506
+			) {
1507
+				continue;
1508
+			}
1509
+			// no nav tab for this config
1510
+			// check for persistent flag
1511
+			if ($slug !== $this->_req_action && isset($config['nav']['persistent']) && ! $config['nav']['persistent']) {
1512
+				// nav tab is only to appear when route requested.
1513
+				continue;
1514
+			}
1515
+			if (! $this->check_user_access($slug, true)) {
1516
+				// no nav tab because current user does not have access.
1517
+				continue;
1518
+			}
1519
+			$css_class = isset($config['css_class']) ? $config['css_class'] . ' ' : '';
1520
+			$this->_nav_tabs[ $slug ] = array(
1521
+				'url'       => isset($config['nav']['url'])
1522
+					? $config['nav']['url']
1523
+					: EE_Admin_Page::add_query_args_and_nonce(
1524
+						array('action' => $slug),
1525
+						$this->_admin_base_url
1526
+					),
1527
+				'link_text' => isset($config['nav']['label'])
1528
+					? $config['nav']['label']
1529
+					: ucwords(
1530
+						str_replace('_', ' ', $slug)
1531
+					),
1532
+				'css_class' => $this->_req_action === $slug ? $css_class . 'nav-tab-active' : $css_class,
1533
+				'order'     => isset($config['nav']['order']) ? $config['nav']['order'] : $i,
1534
+			);
1535
+			$i++;
1536
+		}
1537
+		// if $this->_nav_tabs is empty then lets set the default
1538
+		if (empty($this->_nav_tabs)) {
1539
+			$this->_nav_tabs[ $this->_default_nav_tab_name ] = array(
1540
+				'url'       => $this->_admin_base_url,
1541
+				'link_text' => ucwords(str_replace('_', ' ', $this->_default_nav_tab_name)),
1542
+				'css_class' => 'nav-tab-active',
1543
+				'order'     => 10,
1544
+			);
1545
+		}
1546
+		// now let's sort the tabs according to order
1547
+		usort($this->_nav_tabs, array($this, '_sort_nav_tabs'));
1548
+	}
1549
+
1550
+
1551
+	/**
1552
+	 * _set_current_labels
1553
+	 * This method modifies the _labels property with any optional specific labels indicated in the _page_routes
1554
+	 * property array
1555
+	 *
1556
+	 * @return void
1557
+	 */
1558
+	private function _set_current_labels()
1559
+	{
1560
+		if (is_array($this->_route_config) && isset($this->_route_config['labels'])) {
1561
+			foreach ($this->_route_config['labels'] as $label => $text) {
1562
+				if (is_array($text)) {
1563
+					foreach ($text as $sublabel => $subtext) {
1564
+						$this->_labels[ $label ][ $sublabel ] = $subtext;
1565
+					}
1566
+				} else {
1567
+					$this->_labels[ $label ] = $text;
1568
+				}
1569
+			}
1570
+		}
1571
+	}
1572
+
1573
+
1574
+	/**
1575
+	 *        verifies user access for this admin page
1576
+	 *
1577
+	 * @param string $route_to_check if present then the capability for the route matching this string is checked.
1578
+	 * @param bool   $verify_only    Default is FALSE which means if user check fails then wp_die().  Otherwise just
1579
+	 *                               return false if verify fail.
1580
+	 * @return bool
1581
+	 * @throws InvalidArgumentException
1582
+	 * @throws InvalidDataTypeException
1583
+	 * @throws InvalidInterfaceException
1584
+	 */
1585
+	public function check_user_access($route_to_check = '', $verify_only = false)
1586
+	{
1587
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1588
+		$route_to_check = empty($route_to_check) ? $this->_req_action : $route_to_check;
1589
+		$capability = ! empty($route_to_check) && isset($this->_page_routes[ $route_to_check ])
1590
+					  && is_array(
1591
+						  $this->_page_routes[ $route_to_check ]
1592
+					  )
1593
+					  && ! empty($this->_page_routes[ $route_to_check ]['capability'])
1594
+			? $this->_page_routes[ $route_to_check ]['capability'] : null;
1595
+		if (empty($capability) && empty($route_to_check)) {
1596
+			$capability = is_array($this->_route) && empty($this->_route['capability']) ? 'manage_options'
1597
+				: $this->_route['capability'];
1598
+		} else {
1599
+			$capability = empty($capability) ? 'manage_options' : $capability;
1600
+		}
1601
+		$id = is_array($this->_route) && ! empty($this->_route['obj_id']) ? $this->_route['obj_id'] : 0;
1602
+		if (! defined('DOING_AJAX')
1603
+			&& (
1604
+				! function_exists('is_admin')
1605
+				|| ! EE_Registry::instance()->CAP->current_user_can(
1606
+					$capability,
1607
+					$this->page_slug
1608
+					. '_'
1609
+					. $route_to_check,
1610
+					$id
1611
+				)
1612
+			)
1613
+		) {
1614
+			if ($verify_only) {
1615
+				return false;
1616
+			}
1617
+			if (is_user_logged_in()) {
1618
+				wp_die(__('You do not have access to this route.', 'event_espresso'));
1619
+			} else {
1620
+				return false;
1621
+			}
1622
+		}
1623
+		return true;
1624
+	}
1625
+
1626
+
1627
+	/**
1628
+	 * admin_init_global
1629
+	 * This runs all the code that we want executed within the WP admin_init hook.
1630
+	 * This method executes for ALL EE Admin pages.
1631
+	 *
1632
+	 * @return void
1633
+	 */
1634
+	public function admin_init_global()
1635
+	{
1636
+	}
1637
+
1638
+
1639
+	/**
1640
+	 * wp_loaded_global
1641
+	 * This runs all the code that we want executed within the WP wp_loaded hook.  This method is optional for an
1642
+	 * EE_Admin page and will execute on every EE Admin Page load
1643
+	 *
1644
+	 * @return void
1645
+	 */
1646
+	public function wp_loaded()
1647
+	{
1648
+	}
1649
+
1650
+
1651
+	/**
1652
+	 * admin_notices
1653
+	 * Anything triggered by the 'admin_notices' WP hook should be put in here.  This particular method will apply on
1654
+	 * ALL EE_Admin pages.
1655
+	 *
1656
+	 * @return void
1657
+	 */
1658
+	public function admin_notices_global()
1659
+	{
1660
+		$this->_display_no_javascript_warning();
1661
+		$this->_display_espresso_notices();
1662
+	}
1663
+
1664
+
1665
+	public function network_admin_notices_global()
1666
+	{
1667
+		$this->_display_no_javascript_warning();
1668
+		$this->_display_espresso_notices();
1669
+	}
1670
+
1671
+
1672
+	/**
1673
+	 * admin_footer_scripts_global
1674
+	 * Anything triggered by the 'admin_print_footer_scripts' WP hook should be put in here. This particular method
1675
+	 * will apply on ALL EE_Admin pages.
1676
+	 *
1677
+	 * @return void
1678
+	 */
1679
+	public function admin_footer_scripts_global()
1680
+	{
1681
+		$this->_add_admin_page_ajax_loading_img();
1682
+		$this->_add_admin_page_overlay();
1683
+		// if metaboxes are present we need to add the nonce field
1684
+		if (isset($this->_route_config['metaboxes'])
1685
+			|| isset($this->_route_config['list_table'])
1686
+			|| (isset($this->_route_config['has_metaboxes']) && $this->_route_config['has_metaboxes'])
1687
+		) {
1688
+			wp_nonce_field('closedpostboxes', 'closedpostboxesnonce', false);
1689
+			wp_nonce_field('meta-box-order', 'meta-box-order-nonce', false);
1690
+		}
1691
+	}
1692
+
1693
+
1694
+	/**
1695
+	 * admin_footer_global
1696
+	 * Anything triggered by the wp 'admin_footer' wp hook should be put in here.
1697
+	 * This particular method will apply on ALL EE_Admin Pages.
1698
+	 *
1699
+	 * @return void
1700
+	 * @throws InvalidArgumentException
1701
+	 * @throws InvalidDataTypeException
1702
+	 * @throws InvalidInterfaceException
1703
+	 */
1704
+	public function admin_footer_global()
1705
+	{
1706
+		// dialog container for dialog helper
1707
+		$d_cont = '<div class="ee-admin-dialog-container auto-hide hidden">' . "\n";
1708
+		$d_cont .= '<div class="ee-notices"></div>';
1709
+		$d_cont .= '<div class="ee-admin-dialog-container-inner-content"></div>';
1710
+		$d_cont .= '</div>';
1711
+		echo $d_cont;
1712
+		// help tour stuff?
1713
+		if (isset($this->_help_tour[ $this->_req_action ])) {
1714
+			echo implode('<br />', $this->_help_tour[ $this->_req_action ]);
1715
+		}
1716
+		// current set timezone for timezone js
1717
+		echo '<span id="current_timezone" class="hidden">' . EEH_DTT_Helper::get_timezone() . '</span>';
1718
+	}
1719
+
1720
+
1721
+	/**
1722
+	 * This function sees if there is a method for help popup content existing for the given route.  If there is then
1723
+	 * we'll use the retrieved array to output the content using the template. For child classes: If you want to have
1724
+	 * help popups then in your templates or your content you set "triggers" for the content using the
1725
+	 * "_set_help_trigger('help_trigger_id')" where "help_trigger_id" is what you will use later in your custom method
1726
+	 * for the help popup content on that page. Then in your Child_Admin_Page class you need to define a help popup
1727
+	 * method for the content in the format "_help_popup_content_{route_name}()"  So if you are setting help content
1728
+	 * for the
1729
+	 * 'edit_event' route you should have a method named "_help_popup_content_edit_route". In your defined
1730
+	 * "help_popup_content_..." method.  You must prepare and return an array in the following format array(
1731
+	 *    'help_trigger_id' => array(
1732
+	 *        'title' => esc_html__('localized title for popup', 'event_espresso'),
1733
+	 *        'content' => esc_html__('localized content for popup', 'event_espresso')
1734
+	 *    )
1735
+	 * );
1736
+	 * Then the EE_Admin_Parent will take care of making sure that is setup properly on the correct route.
1737
+	 *
1738
+	 * @param array $help_array
1739
+	 * @param bool  $display
1740
+	 * @return string content
1741
+	 * @throws DomainException
1742
+	 * @throws EE_Error
1743
+	 */
1744
+	protected function _set_help_popup_content($help_array = array(), $display = false)
1745
+	{
1746
+		$content = '';
1747
+		$help_array = empty($help_array) ? $this->_get_help_content() : $help_array;
1748
+		// loop through the array and setup content
1749
+		foreach ($help_array as $trigger => $help) {
1750
+			// make sure the array is setup properly
1751
+			if (! isset($help['title'], $help['content'])) {
1752
+				throw new EE_Error(
1753
+					esc_html__(
1754
+						'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',
1755
+						'event_espresso'
1756
+					)
1757
+				);
1758
+			}
1759
+			// we're good so let'd setup the template vars and then assign parsed template content to our content.
1760
+			$template_args = array(
1761
+				'help_popup_id'      => $trigger,
1762
+				'help_popup_title'   => $help['title'],
1763
+				'help_popup_content' => $help['content'],
1764
+			);
1765
+			$content .= EEH_Template::display_template(
1766
+				EE_ADMIN_TEMPLATE . 'admin_help_popup.template.php',
1767
+				$template_args,
1768
+				true
1769
+			);
1770
+		}
1771
+		if ($display) {
1772
+			echo $content;
1773
+			return '';
1774
+		}
1775
+		return $content;
1776
+	}
1777
+
1778
+
1779
+	/**
1780
+	 * All this does is retrieve the help content array if set by the EE_Admin_Page child
1781
+	 *
1782
+	 * @return array properly formatted array for help popup content
1783
+	 * @throws EE_Error
1784
+	 */
1785
+	private function _get_help_content()
1786
+	{
1787
+		// what is the method we're looking for?
1788
+		$method_name = '_help_popup_content_' . $this->_req_action;
1789
+		// if method doesn't exist let's get out.
1790
+		if (! method_exists($this, $method_name)) {
1791
+			return array();
1792
+		}
1793
+		// k we're good to go let's retrieve the help array
1794
+		$help_array = $this->{$method_name}();
1795
+		// make sure we've got an array!
1796
+		if (! is_array($help_array)) {
1797
+			throw new EE_Error(
1798
+				esc_html__(
1799
+					'Something went wrong with help popup content generation. Expecting an array and well, this ain\'t no array bub.',
1800
+					'event_espresso'
1801
+				)
1802
+			);
1803
+		}
1804
+		return $help_array;
1805
+	}
1806
+
1807
+
1808
+	/**
1809
+	 * EE Admin Pages can use this to set a properly formatted trigger for a help popup.
1810
+	 * By default the trigger html is printed.  Otherwise it can be returned if the $display flag is set "false"
1811
+	 * See comments made on the _set_help_content method for understanding other parts to the help popup tool.
1812
+	 *
1813
+	 * @param string  $trigger_id reference for retrieving the trigger content for the popup
1814
+	 * @param boolean $display    if false then we return the trigger string
1815
+	 * @param array   $dimensions an array of dimensions for the box (array(h,w))
1816
+	 * @return string
1817
+	 * @throws DomainException
1818
+	 * @throws EE_Error
1819
+	 */
1820
+	protected function _set_help_trigger($trigger_id, $display = true, $dimensions = array('400', '640'))
1821
+	{
1822
+		if (defined('DOING_AJAX')) {
1823
+			return '';
1824
+		}
1825
+		// 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
1826
+		$help_array = $this->_get_help_content();
1827
+		$help_content = '';
1828
+		if (empty($help_array) || ! isset($help_array[ $trigger_id ])) {
1829
+			$help_array[ $trigger_id ] = array(
1830
+				'title'   => esc_html__('Missing Content', 'event_espresso'),
1831
+				'content' => esc_html__(
1832
+					'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.)',
1833
+					'event_espresso'
1834
+				),
1835
+			);
1836
+			$help_content = $this->_set_help_popup_content($help_array);
1837
+		}
1838
+		// let's setup the trigger
1839
+		$content = '<a class="ee-dialog" href="?height='
1840
+				   . $dimensions[0]
1841
+				   . '&width='
1842
+				   . $dimensions[1]
1843
+				   . '&inlineId='
1844
+				   . $trigger_id
1845
+				   . '" target="_blank"><span class="question ee-help-popup-question"></span></a>';
1846
+		$content .= $help_content;
1847
+		if ($display) {
1848
+			echo $content;
1849
+			return '';
1850
+		}
1851
+		return $content;
1852
+	}
1853
+
1854
+
1855
+	/**
1856
+	 * _add_global_screen_options
1857
+	 * Add any extra wp_screen_options within this method using built-in WP functions/methods for doing so.
1858
+	 * This particular method will add_screen_options on ALL EE_Admin Pages
1859
+	 *
1860
+	 * @link   http://chrismarslender.com/wp-tutorials/wordpress-screen-options-tutorial/
1861
+	 *         see also WP_Screen object documents...
1862
+	 * @link   http://codex.wordpress.org/Class_Reference/WP_Screen
1863
+	 * @abstract
1864
+	 * @return void
1865
+	 */
1866
+	private function _add_global_screen_options()
1867
+	{
1868
+	}
1869
+
1870
+
1871
+	/**
1872
+	 * _add_global_feature_pointers
1873
+	 * This method is used for implementing any "feature pointers" (using built-in WP styling js).
1874
+	 * This particular method will implement feature pointers for ALL EE_Admin pages.
1875
+	 * Note: this is just a placeholder for now.  Implementation will come down the road
1876
+	 *
1877
+	 * @see    WP_Internal_Pointers class in wp-admin/includes/template.php for example (its a final class so can't be
1878
+	 *         extended) also see:
1879
+	 * @link   http://eamann.com/tech/wordpress-portland/
1880
+	 * @abstract
1881
+	 * @return void
1882
+	 */
1883
+	private function _add_global_feature_pointers()
1884
+	{
1885
+	}
1886
+
1887
+
1888
+	/**
1889
+	 * load_global_scripts_styles
1890
+	 * The scripts and styles enqueued in here will be loaded on every EE Admin page
1891
+	 *
1892
+	 * @return void
1893
+	 * @throws EE_Error
1894
+	 */
1895
+	public function load_global_scripts_styles()
1896
+	{
1897
+		// add debugging styles
1898
+		if (WP_DEBUG) {
1899
+			add_action('admin_head', array($this, 'add_xdebug_style'));
1900
+		}
1901
+		// taking care of metaboxes
1902
+		if (empty($this->_cpt_route)
1903
+			&& (isset($this->_route_config['metaboxes']) || isset($this->_route_config['has_metaboxes']))
1904
+		) {
1905
+			wp_enqueue_script('dashboard');
1906
+		}
1907
+
1908
+		// LOCALIZED DATA
1909
+		// localize script for ajax lazy loading
1910
+		wp_localize_script(
1911
+			EspressoLegacyAdminAssetManager::JS_HANDLE_EE_ADMIN,
1912
+			'eeLazyLoadingContainers',
1913
+			apply_filters(
1914
+				'FHEE__EE_Admin_Page_Core__load_global_scripts_styles__loader_containers',
1915
+				['espresso_news_post_box_content']
1916
+			)
1917
+		);
1918
+		/**
1919
+		 * help tour stuff
1920
+		 */
1921
+		if (EE_Registry::instance()->CFG->admin->help_tour_activation && ! empty($this->_help_tour)) {
1922
+			add_filter('FHEE_load_joyride', '__return_true');
1923
+			$tours = array();
1924
+			// setup tours for the js tour object
1925
+			foreach ($this->_help_tour['tours'] as $tour) {
1926
+				if ($tour instanceof EE_Help_Tour) {
1927
+					$tours[] = array(
1928
+						'id'      => $tour->get_slug(),
1929
+						'options' => $tour->get_options(),
1930
+					);
1931
+				}
1932
+			}
1933
+			wp_localize_script(
1934
+				EspressoLegacyAdminAssetManager::JS_HANDLE_EE_HELP_TOUR,
1935
+				'EE_HELP_TOUR',
1936
+				['tours' => $tours]
1937
+			);
1938
+			// admin_footer_global will take care of making sure our help_tour skeleton gets printed via the info stored in $this->_help_tour
1939
+		}
1940
+	}
1941
+
1942
+
1943
+	/**
1944
+	 *        admin_footer_scripts_eei18n_js_strings
1945
+	 *
1946
+	 * @return        void
1947
+	 */
1948
+	public function admin_footer_scripts_eei18n_js_strings()
1949
+	{
1950
+		EE_Registry::$i18n_js_strings['ajax_url'] = WP_AJAX_URL;
1951
+		EE_Registry::$i18n_js_strings['confirm_delete'] = esc_html__(
1952
+			'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!!!',
1953
+			'event_espresso'
1954
+		);
1955
+		EE_Registry::$i18n_js_strings['January'] = esc_html__('January', 'event_espresso');
1956
+		EE_Registry::$i18n_js_strings['February'] = esc_html__('February', 'event_espresso');
1957
+		EE_Registry::$i18n_js_strings['March'] = esc_html__('March', 'event_espresso');
1958
+		EE_Registry::$i18n_js_strings['April'] = esc_html__('April', 'event_espresso');
1959
+		EE_Registry::$i18n_js_strings['May'] = esc_html__('May', 'event_espresso');
1960
+		EE_Registry::$i18n_js_strings['June'] = esc_html__('June', 'event_espresso');
1961
+		EE_Registry::$i18n_js_strings['July'] = esc_html__('July', 'event_espresso');
1962
+		EE_Registry::$i18n_js_strings['August'] = esc_html__('August', 'event_espresso');
1963
+		EE_Registry::$i18n_js_strings['September'] = esc_html__('September', 'event_espresso');
1964
+		EE_Registry::$i18n_js_strings['October'] = esc_html__('October', 'event_espresso');
1965
+		EE_Registry::$i18n_js_strings['November'] = esc_html__('November', 'event_espresso');
1966
+		EE_Registry::$i18n_js_strings['December'] = esc_html__('December', 'event_espresso');
1967
+		EE_Registry::$i18n_js_strings['Jan'] = esc_html__('Jan', 'event_espresso');
1968
+		EE_Registry::$i18n_js_strings['Feb'] = esc_html__('Feb', 'event_espresso');
1969
+		EE_Registry::$i18n_js_strings['Mar'] = esc_html__('Mar', 'event_espresso');
1970
+		EE_Registry::$i18n_js_strings['Apr'] = esc_html__('Apr', 'event_espresso');
1971
+		EE_Registry::$i18n_js_strings['May'] = esc_html__('May', 'event_espresso');
1972
+		EE_Registry::$i18n_js_strings['Jun'] = esc_html__('Jun', 'event_espresso');
1973
+		EE_Registry::$i18n_js_strings['Jul'] = esc_html__('Jul', 'event_espresso');
1974
+		EE_Registry::$i18n_js_strings['Aug'] = esc_html__('Aug', 'event_espresso');
1975
+		EE_Registry::$i18n_js_strings['Sep'] = esc_html__('Sep', 'event_espresso');
1976
+		EE_Registry::$i18n_js_strings['Oct'] = esc_html__('Oct', 'event_espresso');
1977
+		EE_Registry::$i18n_js_strings['Nov'] = esc_html__('Nov', 'event_espresso');
1978
+		EE_Registry::$i18n_js_strings['Dec'] = esc_html__('Dec', 'event_espresso');
1979
+		EE_Registry::$i18n_js_strings['Sunday'] = esc_html__('Sunday', 'event_espresso');
1980
+		EE_Registry::$i18n_js_strings['Monday'] = esc_html__('Monday', 'event_espresso');
1981
+		EE_Registry::$i18n_js_strings['Tuesday'] = esc_html__('Tuesday', 'event_espresso');
1982
+		EE_Registry::$i18n_js_strings['Wednesday'] = esc_html__('Wednesday', 'event_espresso');
1983
+		EE_Registry::$i18n_js_strings['Thursday'] = esc_html__('Thursday', 'event_espresso');
1984
+		EE_Registry::$i18n_js_strings['Friday'] = esc_html__('Friday', 'event_espresso');
1985
+		EE_Registry::$i18n_js_strings['Saturday'] = esc_html__('Saturday', 'event_espresso');
1986
+		EE_Registry::$i18n_js_strings['Sun'] = esc_html__('Sun', 'event_espresso');
1987
+		EE_Registry::$i18n_js_strings['Mon'] = esc_html__('Mon', 'event_espresso');
1988
+		EE_Registry::$i18n_js_strings['Tue'] = esc_html__('Tue', 'event_espresso');
1989
+		EE_Registry::$i18n_js_strings['Wed'] = esc_html__('Wed', 'event_espresso');
1990
+		EE_Registry::$i18n_js_strings['Thu'] = esc_html__('Thu', 'event_espresso');
1991
+		EE_Registry::$i18n_js_strings['Fri'] = esc_html__('Fri', 'event_espresso');
1992
+		EE_Registry::$i18n_js_strings['Sat'] = esc_html__('Sat', 'event_espresso');
1993
+	}
1994
+
1995
+
1996
+	/**
1997
+	 *        load enhanced xdebug styles for ppl with failing eyesight
1998
+	 *
1999
+	 * @return        void
2000
+	 */
2001
+	public function add_xdebug_style()
2002
+	{
2003
+		echo '<style>.xdebug-error { font-size:1.5em; }</style>';
2004
+	}
2005
+
2006
+
2007
+	/************************/
2008
+	/** LIST TABLE METHODS **/
2009
+	/************************/
2010
+	/**
2011
+	 * this sets up the list table if the current view requires it.
2012
+	 *
2013
+	 * @return void
2014
+	 * @throws EE_Error
2015
+	 * @throws InvalidArgumentException
2016
+	 * @throws InvalidDataTypeException
2017
+	 * @throws InvalidInterfaceException
2018
+	 */
2019
+	protected function _set_list_table()
2020
+	{
2021
+		// first is this a list_table view?
2022
+		if (! isset($this->_route_config['list_table'])) {
2023
+			return;
2024
+		} //not a list_table view so get out.
2025
+		// list table functions are per view specific (because some admin pages might have more than one list table!)
2026
+		$list_table_view = '_set_list_table_views_' . $this->_req_action;
2027
+		if (! method_exists($this, $list_table_view) || $this->{$list_table_view}() === false) {
2028
+			// user error msg
2029
+			$error_msg = esc_html__(
2030
+				'An error occurred. The requested list table views could not be found.',
2031
+				'event_espresso'
2032
+			);
2033
+			// developer error msg
2034
+			$error_msg .= '||'
2035
+						  . sprintf(
2036
+							  esc_html__(
2037
+								  '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.',
2038
+								  'event_espresso'
2039
+							  ),
2040
+							  $this->_req_action,
2041
+							  $list_table_view
2042
+						  );
2043
+			throw new EE_Error($error_msg);
2044
+		}
2045
+		// let's provide the ability to filter the views per PAGE AND ROUTE, per PAGE, and globally
2046
+		$this->_views = apply_filters(
2047
+			'FHEE_list_table_views_' . $this->page_slug . '_' . $this->_req_action,
2048
+			$this->_views
2049
+		);
2050
+		$this->_views = apply_filters('FHEE_list_table_views_' . $this->page_slug, $this->_views);
2051
+		$this->_views = apply_filters('FHEE_list_table_views', $this->_views);
2052
+		$this->_set_list_table_view();
2053
+		$this->_set_list_table_object();
2054
+	}
2055
+
2056
+
2057
+	/**
2058
+	 * set current view for List Table
2059
+	 *
2060
+	 * @return void
2061
+	 */
2062
+	protected function _set_list_table_view()
2063
+	{
2064
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2065
+		// looking at active items or dumpster diving ?
2066
+		if (! isset($this->_req_data['status']) || ! array_key_exists($this->_req_data['status'], $this->_views)) {
2067
+			$this->_view = isset($this->_views['in_use']) ? 'in_use' : 'all';
2068
+		} else {
2069
+			$this->_view = sanitize_key($this->_req_data['status']);
2070
+		}
2071
+	}
2072
+
2073
+
2074
+	/**
2075
+	 * _set_list_table_object
2076
+	 * WP_List_Table objects need to be loaded fairly early so automatic stuff WP does is taken care of.
2077
+	 *
2078
+	 * @throws InvalidInterfaceException
2079
+	 * @throws InvalidArgumentException
2080
+	 * @throws InvalidDataTypeException
2081
+	 * @throws EE_Error
2082
+	 * @throws InvalidInterfaceException
2083
+	 */
2084
+	protected function _set_list_table_object()
2085
+	{
2086
+		if (isset($this->_route_config['list_table'])) {
2087
+			if (! class_exists($this->_route_config['list_table'])) {
2088
+				throw new EE_Error(
2089
+					sprintf(
2090
+						esc_html__(
2091
+							'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.',
2092
+							'event_espresso'
2093
+						),
2094
+						$this->_route_config['list_table'],
2095
+						get_class($this)
2096
+					)
2097
+				);
2098
+			}
2099
+			$this->_list_table_object = $this->loader->getShared(
2100
+				$this->_route_config['list_table'],
2101
+				array($this)
2102
+			);
2103
+		}
2104
+	}
2105
+
2106
+
2107
+	/**
2108
+	 * get_list_table_view_RLs - get it? View RL ?? VU-RL???  URL ??
2109
+	 *
2110
+	 * @param array $extra_query_args                     Optional. An array of extra query args to add to the generated
2111
+	 *                                                    urls.  The array should be indexed by the view it is being
2112
+	 *                                                    added to.
2113
+	 * @return array
2114
+	 */
2115
+	public function get_list_table_view_RLs($extra_query_args = array())
2116
+	{
2117
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2118
+		if (empty($this->_views)) {
2119
+			$this->_views = array();
2120
+		}
2121
+		// cycle thru views
2122
+		foreach ($this->_views as $key => $view) {
2123
+			$query_args = array();
2124
+			// check for current view
2125
+			$this->_views[ $key ]['class'] = $this->_view === $view['slug'] ? 'current' : '';
2126
+			$query_args['action'] = $this->_req_action;
2127
+			$query_args[ $this->_req_action . '_nonce' ] = wp_create_nonce($query_args['action'] . '_nonce');
2128
+			$query_args['status'] = $view['slug'];
2129
+			// merge any other arguments sent in.
2130
+			if (isset($extra_query_args[ $view['slug'] ])) {
2131
+				foreach ($extra_query_args[ $view['slug'] ] as $extra_query_arg) {
2132
+					$query_args[] = $extra_query_arg;
2133
+				}
2134
+			}
2135
+			$this->_views[ $key ]['url'] = EE_Admin_Page::add_query_args_and_nonce($query_args, $this->_admin_base_url);
2136
+		}
2137
+		return $this->_views;
2138
+	}
2139
+
2140
+
2141
+	/**
2142
+	 * _entries_per_page_dropdown
2143
+	 * generates a drop down box for selecting the number of visible rows in an admin page list table
2144
+	 *
2145
+	 * @todo   : Note: ideally this should be added to the screen options dropdown as that would be consistent with how
2146
+	 *         WP does it.
2147
+	 * @param int $max_entries total number of rows in the table
2148
+	 * @return string
2149
+	 */
2150
+	protected function _entries_per_page_dropdown($max_entries = 0)
2151
+	{
2152
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2153
+		$values = array(10, 25, 50, 100);
2154
+		$per_page = (! empty($this->_req_data['per_page'])) ? absint($this->_req_data['per_page']) : 10;
2155
+		if ($max_entries) {
2156
+			$values[] = $max_entries;
2157
+			sort($values);
2158
+		}
2159
+		$entries_per_page_dropdown = '
2160 2160
 			<div id="entries-per-page-dv" class="alignleft actions">
2161 2161
 				<label class="hide-if-no-js">
2162 2162
 					Show
2163 2163
 					<select id="entries-per-page-slct" name="entries-per-page-slct">';
2164
-        foreach ($values as $value) {
2165
-            if ($value < $max_entries) {
2166
-                $selected = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2167
-                $entries_per_page_dropdown .= '
2164
+		foreach ($values as $value) {
2165
+			if ($value < $max_entries) {
2166
+				$selected = $value === $per_page ? ' selected="' . $per_page . '"' : '';
2167
+				$entries_per_page_dropdown .= '
2168 2168
 						<option value="' . $value . '"' . $selected . '>' . $value . '&nbsp;&nbsp;</option>';
2169
-            }
2170
-        }
2171
-        $selected = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2172
-        $entries_per_page_dropdown .= '
2169
+			}
2170
+		}
2171
+		$selected = $max_entries === $per_page ? ' selected="' . $per_page . '"' : '';
2172
+		$entries_per_page_dropdown .= '
2173 2173
 						<option value="' . $max_entries . '"' . $selected . '>All&nbsp;&nbsp;</option>';
2174
-        $entries_per_page_dropdown .= '
2174
+		$entries_per_page_dropdown .= '
2175 2175
 					</select>
2176 2176
 					entries
2177 2177
 				</label>
2178 2178
 				<input id="entries-per-page-btn" class="button-secondary" type="submit" value="Go" >
2179 2179
 			</div>
2180 2180
 		';
2181
-        return $entries_per_page_dropdown;
2182
-    }
2183
-
2184
-
2185
-    /**
2186
-     *        _set_search_attributes
2187
-     *
2188
-     * @return        void
2189
-     */
2190
-    public function _set_search_attributes()
2191
-    {
2192
-        $this->_template_args['search']['btn_label'] = sprintf(
2193
-            esc_html__('Search %s', 'event_espresso'),
2194
-            empty($this->_search_btn_label) ? $this->page_label
2195
-                : $this->_search_btn_label
2196
-        );
2197
-        $this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
2198
-    }
2199
-
2200
-
2201
-
2202
-    /*** END LIST TABLE METHODS **/
2203
-
2204
-
2205
-    /**
2206
-     * _add_registered_metaboxes
2207
-     *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2208
-     *
2209
-     * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2210
-     * @return void
2211
-     * @throws EE_Error
2212
-     */
2213
-    private function _add_registered_meta_boxes()
2214
-    {
2215
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2216
-        // we only add meta boxes if the page_route calls for it
2217
-        if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2218
-            && is_array(
2219
-                $this->_route_config['metaboxes']
2220
-            )
2221
-        ) {
2222
-            // this simply loops through the callbacks provided
2223
-            // and checks if there is a corresponding callback registered by the child
2224
-            // if there is then we go ahead and process the metabox loader.
2225
-            foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2226
-                // first check for Closures
2227
-                if ($metabox_callback instanceof Closure) {
2228
-                    $result = $metabox_callback();
2229
-                } elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2230
-                    $result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
2231
-                } else {
2232
-                    $result = $this->{$metabox_callback}();
2233
-                }
2234
-                if ($result === false) {
2235
-                    // user error msg
2236
-                    $error_msg = esc_html__(
2237
-                        'An error occurred. The  requested metabox could not be found.',
2238
-                        'event_espresso'
2239
-                    );
2240
-                    // developer error msg
2241
-                    $error_msg .= '||'
2242
-                                  . sprintf(
2243
-                                      esc_html__(
2244
-                                          '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.',
2245
-                                          'event_espresso'
2246
-                                      ),
2247
-                                      $metabox_callback
2248
-                                  );
2249
-                    throw new EE_Error($error_msg);
2250
-                }
2251
-            }
2252
-        }
2253
-    }
2254
-
2255
-
2256
-    /**
2257
-     * _add_screen_columns
2258
-     * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2259
-     * the dynamic column template and we'll setup the column options for the page.
2260
-     *
2261
-     * @return void
2262
-     */
2263
-    private function _add_screen_columns()
2264
-    {
2265
-        if (is_array($this->_route_config)
2266
-            && isset($this->_route_config['columns'])
2267
-            && is_array($this->_route_config['columns'])
2268
-            && count($this->_route_config['columns']) === 2
2269
-        ) {
2270
-            add_screen_option(
2271
-                'layout_columns',
2272
-                array(
2273
-                    'max'     => (int) $this->_route_config['columns'][0],
2274
-                    'default' => (int) $this->_route_config['columns'][1],
2275
-                )
2276
-            );
2277
-            $this->_template_args['num_columns'] = $this->_route_config['columns'][0];
2278
-            $screen_id = $this->_current_screen->id;
2279
-            $screen_columns = (int) get_user_option("screen_layout_{$screen_id}");
2280
-            $total_columns = ! empty($screen_columns)
2281
-                ? $screen_columns
2282
-                : $this->_route_config['columns'][1];
2283
-            $this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2284
-            $this->_template_args['current_page'] = $this->_wp_page_slug;
2285
-            $this->_template_args['screen'] = $this->_current_screen;
2286
-            $this->_column_template_path = EE_ADMIN_TEMPLATE
2287
-                                           . 'admin_details_metabox_column_wrapper.template.php';
2288
-            // finally if we don't have has_metaboxes set in the route config
2289
-            // let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2290
-            $this->_route_config['has_metaboxes'] = true;
2291
-        }
2292
-    }
2293
-
2294
-
2295
-
2296
-    /** GLOBALLY AVAILABLE METABOXES **/
2297
-
2298
-
2299
-    /**
2300
-     * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2301
-     * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2302
-     * these get loaded on.
2303
-     */
2304
-    private function _espresso_news_post_box()
2305
-    {
2306
-        $news_box_title = apply_filters(
2307
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2308
-            esc_html__('New @ Event Espresso', 'event_espresso')
2309
-        );
2310
-        add_meta_box(
2311
-            'espresso_news_post_box',
2312
-            $news_box_title,
2313
-            array(
2314
-                $this,
2315
-                'espresso_news_post_box',
2316
-            ),
2317
-            $this->_wp_page_slug,
2318
-            'side'
2319
-        );
2320
-    }
2321
-
2322
-
2323
-    /**
2324
-     * Code for setting up espresso ratings request metabox.
2325
-     */
2326
-    protected function _espresso_ratings_request()
2327
-    {
2328
-        if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2329
-            return;
2330
-        }
2331
-        $ratings_box_title = apply_filters(
2332
-            'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2333
-            esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2334
-        );
2335
-        add_meta_box(
2336
-            'espresso_ratings_request',
2337
-            $ratings_box_title,
2338
-            array(
2339
-                $this,
2340
-                'espresso_ratings_request',
2341
-            ),
2342
-            $this->_wp_page_slug,
2343
-            'side'
2344
-        );
2345
-    }
2346
-
2347
-
2348
-    /**
2349
-     * Code for setting up espresso ratings request metabox content.
2350
-     *
2351
-     * @throws DomainException
2352
-     */
2353
-    public function espresso_ratings_request()
2354
-    {
2355
-        EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2356
-    }
2357
-
2358
-
2359
-    public static function cached_rss_display($rss_id, $url)
2360
-    {
2361
-        $loading = '<p class="widget-loading hide-if-no-js">'
2362
-                   . __('Loading&#8230;', 'event_espresso')
2363
-                   . '</p><p class="hide-if-js">'
2364
-                   . esc_html__('This widget requires JavaScript.', 'event_espresso')
2365
-                   . '</p>';
2366
-        $pre = '<div class="espresso-rss-display">' . "\n\t";
2367
-        $pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2368
-        $post = '</div>' . "\n";
2369
-        $cache_key = 'ee_rss_' . md5($rss_id);
2370
-        $output = get_transient($cache_key);
2371
-        if ($output !== false) {
2372
-            echo $pre . $output . $post;
2373
-            return true;
2374
-        }
2375
-        if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2376
-            echo $pre . $loading . $post;
2377
-            return false;
2378
-        }
2379
-        ob_start();
2380
-        wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
2381
-        set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2382
-        return true;
2383
-    }
2384
-
2385
-
2386
-    public function espresso_news_post_box()
2387
-    {
2388
-        ?>
2181
+		return $entries_per_page_dropdown;
2182
+	}
2183
+
2184
+
2185
+	/**
2186
+	 *        _set_search_attributes
2187
+	 *
2188
+	 * @return        void
2189
+	 */
2190
+	public function _set_search_attributes()
2191
+	{
2192
+		$this->_template_args['search']['btn_label'] = sprintf(
2193
+			esc_html__('Search %s', 'event_espresso'),
2194
+			empty($this->_search_btn_label) ? $this->page_label
2195
+				: $this->_search_btn_label
2196
+		);
2197
+		$this->_template_args['search']['callback'] = 'search_' . $this->page_slug;
2198
+	}
2199
+
2200
+
2201
+
2202
+	/*** END LIST TABLE METHODS **/
2203
+
2204
+
2205
+	/**
2206
+	 * _add_registered_metaboxes
2207
+	 *  this loads any registered metaboxes via the 'metaboxes' index in the _page_config property array.
2208
+	 *
2209
+	 * @link   http://codex.wordpress.org/Function_Reference/add_meta_box
2210
+	 * @return void
2211
+	 * @throws EE_Error
2212
+	 */
2213
+	private function _add_registered_meta_boxes()
2214
+	{
2215
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2216
+		// we only add meta boxes if the page_route calls for it
2217
+		if (is_array($this->_route_config) && isset($this->_route_config['metaboxes'])
2218
+			&& is_array(
2219
+				$this->_route_config['metaboxes']
2220
+			)
2221
+		) {
2222
+			// this simply loops through the callbacks provided
2223
+			// and checks if there is a corresponding callback registered by the child
2224
+			// if there is then we go ahead and process the metabox loader.
2225
+			foreach ($this->_route_config['metaboxes'] as $metabox_callback) {
2226
+				// first check for Closures
2227
+				if ($metabox_callback instanceof Closure) {
2228
+					$result = $metabox_callback();
2229
+				} elseif (is_array($metabox_callback) && isset($metabox_callback[0], $metabox_callback[1])) {
2230
+					$result = call_user_func(array($metabox_callback[0], $metabox_callback[1]));
2231
+				} else {
2232
+					$result = $this->{$metabox_callback}();
2233
+				}
2234
+				if ($result === false) {
2235
+					// user error msg
2236
+					$error_msg = esc_html__(
2237
+						'An error occurred. The  requested metabox could not be found.',
2238
+						'event_espresso'
2239
+					);
2240
+					// developer error msg
2241
+					$error_msg .= '||'
2242
+								  . sprintf(
2243
+									  esc_html__(
2244
+										  '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.',
2245
+										  'event_espresso'
2246
+									  ),
2247
+									  $metabox_callback
2248
+								  );
2249
+					throw new EE_Error($error_msg);
2250
+				}
2251
+			}
2252
+		}
2253
+	}
2254
+
2255
+
2256
+	/**
2257
+	 * _add_screen_columns
2258
+	 * This will check the _page_config array and if there is "columns" key index indicated, we'll set the template as
2259
+	 * the dynamic column template and we'll setup the column options for the page.
2260
+	 *
2261
+	 * @return void
2262
+	 */
2263
+	private function _add_screen_columns()
2264
+	{
2265
+		if (is_array($this->_route_config)
2266
+			&& isset($this->_route_config['columns'])
2267
+			&& is_array($this->_route_config['columns'])
2268
+			&& count($this->_route_config['columns']) === 2
2269
+		) {
2270
+			add_screen_option(
2271
+				'layout_columns',
2272
+				array(
2273
+					'max'     => (int) $this->_route_config['columns'][0],
2274
+					'default' => (int) $this->_route_config['columns'][1],
2275
+				)
2276
+			);
2277
+			$this->_template_args['num_columns'] = $this->_route_config['columns'][0];
2278
+			$screen_id = $this->_current_screen->id;
2279
+			$screen_columns = (int) get_user_option("screen_layout_{$screen_id}");
2280
+			$total_columns = ! empty($screen_columns)
2281
+				? $screen_columns
2282
+				: $this->_route_config['columns'][1];
2283
+			$this->_template_args['current_screen_widget_class'] = 'columns-' . $total_columns;
2284
+			$this->_template_args['current_page'] = $this->_wp_page_slug;
2285
+			$this->_template_args['screen'] = $this->_current_screen;
2286
+			$this->_column_template_path = EE_ADMIN_TEMPLATE
2287
+										   . 'admin_details_metabox_column_wrapper.template.php';
2288
+			// finally if we don't have has_metaboxes set in the route config
2289
+			// let's make sure it IS set other wise the necessary hidden fields for this won't be loaded.
2290
+			$this->_route_config['has_metaboxes'] = true;
2291
+		}
2292
+	}
2293
+
2294
+
2295
+
2296
+	/** GLOBALLY AVAILABLE METABOXES **/
2297
+
2298
+
2299
+	/**
2300
+	 * In this section we put any globally available EE metaboxes for all EE Admin pages.  They are called by simply
2301
+	 * referencing the callback in the _page_config array property.  This way you can be very specific about what pages
2302
+	 * these get loaded on.
2303
+	 */
2304
+	private function _espresso_news_post_box()
2305
+	{
2306
+		$news_box_title = apply_filters(
2307
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2308
+			esc_html__('New @ Event Espresso', 'event_espresso')
2309
+		);
2310
+		add_meta_box(
2311
+			'espresso_news_post_box',
2312
+			$news_box_title,
2313
+			array(
2314
+				$this,
2315
+				'espresso_news_post_box',
2316
+			),
2317
+			$this->_wp_page_slug,
2318
+			'side'
2319
+		);
2320
+	}
2321
+
2322
+
2323
+	/**
2324
+	 * Code for setting up espresso ratings request metabox.
2325
+	 */
2326
+	protected function _espresso_ratings_request()
2327
+	{
2328
+		if (! apply_filters('FHEE_show_ratings_request_meta_box', true)) {
2329
+			return;
2330
+		}
2331
+		$ratings_box_title = apply_filters(
2332
+			'FHEE__EE_Admin_Page___espresso_news_post_box__news_box_title',
2333
+			esc_html__('Keep Event Espresso Decaf Free', 'event_espresso')
2334
+		);
2335
+		add_meta_box(
2336
+			'espresso_ratings_request',
2337
+			$ratings_box_title,
2338
+			array(
2339
+				$this,
2340
+				'espresso_ratings_request',
2341
+			),
2342
+			$this->_wp_page_slug,
2343
+			'side'
2344
+		);
2345
+	}
2346
+
2347
+
2348
+	/**
2349
+	 * Code for setting up espresso ratings request metabox content.
2350
+	 *
2351
+	 * @throws DomainException
2352
+	 */
2353
+	public function espresso_ratings_request()
2354
+	{
2355
+		EEH_Template::display_template(EE_ADMIN_TEMPLATE . 'espresso_ratings_request_content.template.php');
2356
+	}
2357
+
2358
+
2359
+	public static function cached_rss_display($rss_id, $url)
2360
+	{
2361
+		$loading = '<p class="widget-loading hide-if-no-js">'
2362
+				   . __('Loading&#8230;', 'event_espresso')
2363
+				   . '</p><p class="hide-if-js">'
2364
+				   . esc_html__('This widget requires JavaScript.', 'event_espresso')
2365
+				   . '</p>';
2366
+		$pre = '<div class="espresso-rss-display">' . "\n\t";
2367
+		$pre .= '<span id="' . $rss_id . '_url" class="hidden">' . $url . '</span>';
2368
+		$post = '</div>' . "\n";
2369
+		$cache_key = 'ee_rss_' . md5($rss_id);
2370
+		$output = get_transient($cache_key);
2371
+		if ($output !== false) {
2372
+			echo $pre . $output . $post;
2373
+			return true;
2374
+		}
2375
+		if (! (defined('DOING_AJAX') && DOING_AJAX)) {
2376
+			echo $pre . $loading . $post;
2377
+			return false;
2378
+		}
2379
+		ob_start();
2380
+		wp_widget_rss_output($url, array('show_date' => 0, 'items' => 5));
2381
+		set_transient($cache_key, ob_get_flush(), 12 * HOUR_IN_SECONDS);
2382
+		return true;
2383
+	}
2384
+
2385
+
2386
+	public function espresso_news_post_box()
2387
+	{
2388
+		?>
2389 2389
         <div class="padding">
2390 2390
             <div id="espresso_news_post_box_content" class="infolinks">
2391 2391
                 <?php
2392
-                // Get RSS Feed(s)
2393
-                EE_Admin_Page::cached_rss_display(
2394
-                    'espresso_news_post_box_content',
2395
-                    urlencode(
2396
-                        apply_filters(
2397
-                            'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2398
-                            'http://eventespresso.com/feed/'
2399
-                        )
2400
-                    )
2401
-                );
2402
-                ?>
2392
+				// Get RSS Feed(s)
2393
+				EE_Admin_Page::cached_rss_display(
2394
+					'espresso_news_post_box_content',
2395
+					urlencode(
2396
+						apply_filters(
2397
+							'FHEE__EE_Admin_Page__espresso_news_post_box__feed_url',
2398
+							'http://eventespresso.com/feed/'
2399
+						)
2400
+					)
2401
+				);
2402
+				?>
2403 2403
             </div>
2404 2404
             <?php do_action('AHEE__EE_Admin_Page__espresso_news_post_box__after_content'); ?>
2405 2405
         </div>
2406 2406
         <?php
2407
-    }
2408
-
2409
-
2410
-    private function _espresso_links_post_box()
2411
-    {
2412
-        // Hiding until we actually have content to put in here...
2413
-        // add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2414
-    }
2415
-
2416
-
2417
-    public function espresso_links_post_box()
2418
-    {
2419
-        // Hiding until we actually have content to put in here...
2420
-        // EEH_Template::display_template(
2421
-        //     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2422
-        // );
2423
-    }
2424
-
2425
-
2426
-    protected function _espresso_sponsors_post_box()
2427
-    {
2428
-        if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2429
-            add_meta_box(
2430
-                'espresso_sponsors_post_box',
2431
-                esc_html__('Event Espresso Highlights', 'event_espresso'),
2432
-                array($this, 'espresso_sponsors_post_box'),
2433
-                $this->_wp_page_slug,
2434
-                'side'
2435
-            );
2436
-        }
2437
-    }
2438
-
2439
-
2440
-    public function espresso_sponsors_post_box()
2441
-    {
2442
-        EEH_Template::display_template(
2443
-            EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2444
-        );
2445
-    }
2446
-
2447
-
2448
-    private function _publish_post_box()
2449
-    {
2450
-        $meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2451
-        // if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2452
-        // then we'll use that for the metabox label.
2453
-        // Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2454
-        if (! empty($this->_labels['publishbox'])) {
2455
-            $box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2456
-                : $this->_labels['publishbox'];
2457
-        } else {
2458
-            $box_label = esc_html__('Publish', 'event_espresso');
2459
-        }
2460
-        $box_label = apply_filters(
2461
-            'FHEE__EE_Admin_Page___publish_post_box__box_label',
2462
-            $box_label,
2463
-            $this->_req_action,
2464
-            $this
2465
-        );
2466
-        add_meta_box(
2467
-            $meta_box_ref,
2468
-            $box_label,
2469
-            array($this, 'editor_overview'),
2470
-            $this->_current_screen->id,
2471
-            'side',
2472
-            'high'
2473
-        );
2474
-    }
2475
-
2476
-
2477
-    public function editor_overview()
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'] = isset($this->_template_args['publish_box_extra_content'])
2481
-            ? $this->_template_args['publish_box_extra_content']
2482
-            : '';
2483
-        echo EEH_Template::display_template(
2484
-            EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2485
-            $this->_template_args,
2486
-            true
2487
-        );
2488
-    }
2489
-
2490
-
2491
-    /** end of globally available metaboxes section **/
2492
-
2493
-
2494
-    /**
2495
-     * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2496
-     * protected method.
2497
-     *
2498
-     * @see   $this->_set_publish_post_box_vars for param details
2499
-     * @since 4.6.0
2500
-     * @param string $name
2501
-     * @param int    $id
2502
-     * @param bool   $delete
2503
-     * @param string $save_close_redirect_URL
2504
-     * @param bool   $both_btns
2505
-     * @throws EE_Error
2506
-     * @throws InvalidArgumentException
2507
-     * @throws InvalidDataTypeException
2508
-     * @throws InvalidInterfaceException
2509
-     */
2510
-    public function set_publish_post_box_vars(
2511
-        $name = '',
2512
-        $id = 0,
2513
-        $delete = false,
2514
-        $save_close_redirect_URL = '',
2515
-        $both_btns = true
2516
-    ) {
2517
-        $this->_set_publish_post_box_vars(
2518
-            $name,
2519
-            $id,
2520
-            $delete,
2521
-            $save_close_redirect_URL,
2522
-            $both_btns
2523
-        );
2524
-    }
2525
-
2526
-
2527
-    /**
2528
-     * Sets the _template_args arguments used by the _publish_post_box shortcut
2529
-     * Note: currently there is no validation for this.  However if you want the delete button, the
2530
-     * save, and save and close buttons to work properly, then you will want to include a
2531
-     * values for the name and id arguments.
2532
-     *
2533
-     * @todo  Add in validation for name/id arguments.
2534
-     * @param    string  $name                    key used for the action ID (i.e. event_id)
2535
-     * @param    int     $id                      id attached to the item published
2536
-     * @param    string  $delete                  page route callback for the delete action
2537
-     * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2538
-     * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just
2539
-     *                                            the Save button
2540
-     * @throws EE_Error
2541
-     * @throws InvalidArgumentException
2542
-     * @throws InvalidDataTypeException
2543
-     * @throws InvalidInterfaceException
2544
-     */
2545
-    protected function _set_publish_post_box_vars(
2546
-        $name = '',
2547
-        $id = 0,
2548
-        $delete = '',
2549
-        $save_close_redirect_URL = '',
2550
-        $both_btns = true
2551
-    ) {
2552
-        // if Save & Close, use a custom redirect URL or default to the main page?
2553
-        $save_close_redirect_URL = ! empty($save_close_redirect_URL)
2554
-            ? $save_close_redirect_URL
2555
-            : $this->_admin_base_url;
2556
-        // create the Save & Close and Save buttons
2557
-        $this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2558
-        // if we have extra content set let's add it in if not make sure its empty
2559
-        $this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2560
-            ? $this->_template_args['publish_box_extra_content']
2561
-            : '';
2562
-        if ($delete && ! empty($id)) {
2563
-            // make sure we have a default if just true is sent.
2564
-            $delete = ! empty($delete) ? $delete : 'delete';
2565
-            $delete_link_args = array($name => $id);
2566
-            $delete = $this->get_action_link_or_button(
2567
-                $delete,
2568
-                $delete,
2569
-                $delete_link_args,
2570
-                'submitdelete deletion'
2571
-            );
2572
-        }
2573
-        $this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2574
-        if (! empty($name) && ! empty($id)) {
2575
-            $hidden_field_arr[ $name ] = array(
2576
-                'type'  => 'hidden',
2577
-                'value' => $id,
2578
-            );
2579
-            $hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2580
-        } else {
2581
-            $hf = '';
2582
-        }
2583
-        // add hidden field
2584
-        $this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2585
-            ? $hf[ $name ]['field']
2586
-            : $hf;
2587
-    }
2588
-
2589
-
2590
-    /**
2591
-     * displays an error message to ppl who have javascript disabled
2592
-     *
2593
-     * @return void
2594
-     */
2595
-    private function _display_no_javascript_warning()
2596
-    {
2597
-        ?>
2407
+	}
2408
+
2409
+
2410
+	private function _espresso_links_post_box()
2411
+	{
2412
+		// Hiding until we actually have content to put in here...
2413
+		// add_meta_box('espresso_links_post_box', esc_html__('Helpful Plugin Links', 'event_espresso'), array( $this, 'espresso_links_post_box'), $this->_wp_page_slug, 'side');
2414
+	}
2415
+
2416
+
2417
+	public function espresso_links_post_box()
2418
+	{
2419
+		// Hiding until we actually have content to put in here...
2420
+		// EEH_Template::display_template(
2421
+		//     EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_links.template.php'
2422
+		// );
2423
+	}
2424
+
2425
+
2426
+	protected function _espresso_sponsors_post_box()
2427
+	{
2428
+		if (apply_filters('FHEE_show_sponsors_meta_box', true)) {
2429
+			add_meta_box(
2430
+				'espresso_sponsors_post_box',
2431
+				esc_html__('Event Espresso Highlights', 'event_espresso'),
2432
+				array($this, 'espresso_sponsors_post_box'),
2433
+				$this->_wp_page_slug,
2434
+				'side'
2435
+			);
2436
+		}
2437
+	}
2438
+
2439
+
2440
+	public function espresso_sponsors_post_box()
2441
+	{
2442
+		EEH_Template::display_template(
2443
+			EE_ADMIN_TEMPLATE . 'admin_general_metabox_contents_espresso_sponsors.template.php'
2444
+		);
2445
+	}
2446
+
2447
+
2448
+	private function _publish_post_box()
2449
+	{
2450
+		$meta_box_ref = 'espresso_' . $this->page_slug . '_editor_overview';
2451
+		// if there is a array('label' => array('publishbox' => 'some title') ) present in the _page_config array
2452
+		// then we'll use that for the metabox label.
2453
+		// Otherwise we'll just use publish (publishbox itself could be an array of labels indexed by routes)
2454
+		if (! empty($this->_labels['publishbox'])) {
2455
+			$box_label = is_array($this->_labels['publishbox']) ? $this->_labels['publishbox'][ $this->_req_action ]
2456
+				: $this->_labels['publishbox'];
2457
+		} else {
2458
+			$box_label = esc_html__('Publish', 'event_espresso');
2459
+		}
2460
+		$box_label = apply_filters(
2461
+			'FHEE__EE_Admin_Page___publish_post_box__box_label',
2462
+			$box_label,
2463
+			$this->_req_action,
2464
+			$this
2465
+		);
2466
+		add_meta_box(
2467
+			$meta_box_ref,
2468
+			$box_label,
2469
+			array($this, 'editor_overview'),
2470
+			$this->_current_screen->id,
2471
+			'side',
2472
+			'high'
2473
+		);
2474
+	}
2475
+
2476
+
2477
+	public function editor_overview()
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'] = isset($this->_template_args['publish_box_extra_content'])
2481
+			? $this->_template_args['publish_box_extra_content']
2482
+			: '';
2483
+		echo EEH_Template::display_template(
2484
+			EE_ADMIN_TEMPLATE . 'admin_details_publish_metabox.template.php',
2485
+			$this->_template_args,
2486
+			true
2487
+		);
2488
+	}
2489
+
2490
+
2491
+	/** end of globally available metaboxes section **/
2492
+
2493
+
2494
+	/**
2495
+	 * Public wrapper for the protected method.  Allows plugins/addons to externally call the
2496
+	 * protected method.
2497
+	 *
2498
+	 * @see   $this->_set_publish_post_box_vars for param details
2499
+	 * @since 4.6.0
2500
+	 * @param string $name
2501
+	 * @param int    $id
2502
+	 * @param bool   $delete
2503
+	 * @param string $save_close_redirect_URL
2504
+	 * @param bool   $both_btns
2505
+	 * @throws EE_Error
2506
+	 * @throws InvalidArgumentException
2507
+	 * @throws InvalidDataTypeException
2508
+	 * @throws InvalidInterfaceException
2509
+	 */
2510
+	public function set_publish_post_box_vars(
2511
+		$name = '',
2512
+		$id = 0,
2513
+		$delete = false,
2514
+		$save_close_redirect_URL = '',
2515
+		$both_btns = true
2516
+	) {
2517
+		$this->_set_publish_post_box_vars(
2518
+			$name,
2519
+			$id,
2520
+			$delete,
2521
+			$save_close_redirect_URL,
2522
+			$both_btns
2523
+		);
2524
+	}
2525
+
2526
+
2527
+	/**
2528
+	 * Sets the _template_args arguments used by the _publish_post_box shortcut
2529
+	 * Note: currently there is no validation for this.  However if you want the delete button, the
2530
+	 * save, and save and close buttons to work properly, then you will want to include a
2531
+	 * values for the name and id arguments.
2532
+	 *
2533
+	 * @todo  Add in validation for name/id arguments.
2534
+	 * @param    string  $name                    key used for the action ID (i.e. event_id)
2535
+	 * @param    int     $id                      id attached to the item published
2536
+	 * @param    string  $delete                  page route callback for the delete action
2537
+	 * @param    string  $save_close_redirect_URL custom URL to redirect to after Save & Close has been completed
2538
+	 * @param    boolean $both_btns               whether to display BOTH the "Save & Close" and "Save" buttons or just
2539
+	 *                                            the Save button
2540
+	 * @throws EE_Error
2541
+	 * @throws InvalidArgumentException
2542
+	 * @throws InvalidDataTypeException
2543
+	 * @throws InvalidInterfaceException
2544
+	 */
2545
+	protected function _set_publish_post_box_vars(
2546
+		$name = '',
2547
+		$id = 0,
2548
+		$delete = '',
2549
+		$save_close_redirect_URL = '',
2550
+		$both_btns = true
2551
+	) {
2552
+		// if Save & Close, use a custom redirect URL or default to the main page?
2553
+		$save_close_redirect_URL = ! empty($save_close_redirect_URL)
2554
+			? $save_close_redirect_URL
2555
+			: $this->_admin_base_url;
2556
+		// create the Save & Close and Save buttons
2557
+		$this->_set_save_buttons($both_btns, array(), array(), $save_close_redirect_URL);
2558
+		// if we have extra content set let's add it in if not make sure its empty
2559
+		$this->_template_args['publish_box_extra_content'] = isset($this->_template_args['publish_box_extra_content'])
2560
+			? $this->_template_args['publish_box_extra_content']
2561
+			: '';
2562
+		if ($delete && ! empty($id)) {
2563
+			// make sure we have a default if just true is sent.
2564
+			$delete = ! empty($delete) ? $delete : 'delete';
2565
+			$delete_link_args = array($name => $id);
2566
+			$delete = $this->get_action_link_or_button(
2567
+				$delete,
2568
+				$delete,
2569
+				$delete_link_args,
2570
+				'submitdelete deletion'
2571
+			);
2572
+		}
2573
+		$this->_template_args['publish_delete_link'] = ! empty($id) ? $delete : '';
2574
+		if (! empty($name) && ! empty($id)) {
2575
+			$hidden_field_arr[ $name ] = array(
2576
+				'type'  => 'hidden',
2577
+				'value' => $id,
2578
+			);
2579
+			$hf = $this->_generate_admin_form_fields($hidden_field_arr, 'array');
2580
+		} else {
2581
+			$hf = '';
2582
+		}
2583
+		// add hidden field
2584
+		$this->_template_args['publish_hidden_fields'] = is_array($hf) && ! empty($name)
2585
+			? $hf[ $name ]['field']
2586
+			: $hf;
2587
+	}
2588
+
2589
+
2590
+	/**
2591
+	 * displays an error message to ppl who have javascript disabled
2592
+	 *
2593
+	 * @return void
2594
+	 */
2595
+	private function _display_no_javascript_warning()
2596
+	{
2597
+		?>
2598 2598
         <noscript>
2599 2599
             <div id="no-js-message" class="error">
2600 2600
                 <p style="font-size:1.3em;">
2601 2601
                     <span style="color:red;"><?php esc_html_e('Warning!', 'event_espresso'); ?></span>
2602 2602
                     <?php esc_html_e(
2603
-                        '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.',
2604
-                        'event_espresso'
2605
-                    ); ?>
2603
+						'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.',
2604
+						'event_espresso'
2605
+					); ?>
2606 2606
                 </p>
2607 2607
             </div>
2608 2608
         </noscript>
2609 2609
         <?php
2610
-    }
2611
-
2612
-
2613
-    /**
2614
-     * displays espresso success and/or error notices
2615
-     *
2616
-     * @return void
2617
-     */
2618
-    private function _display_espresso_notices()
2619
-    {
2620
-        $notices = $this->_get_transient(true);
2621
-        echo stripslashes($notices);
2622
-    }
2623
-
2624
-
2625
-    /**
2626
-     * spinny things pacify the masses
2627
-     *
2628
-     * @return void
2629
-     */
2630
-    protected function _add_admin_page_ajax_loading_img()
2631
-    {
2632
-        ?>
2610
+	}
2611
+
2612
+
2613
+	/**
2614
+	 * displays espresso success and/or error notices
2615
+	 *
2616
+	 * @return void
2617
+	 */
2618
+	private function _display_espresso_notices()
2619
+	{
2620
+		$notices = $this->_get_transient(true);
2621
+		echo stripslashes($notices);
2622
+	}
2623
+
2624
+
2625
+	/**
2626
+	 * spinny things pacify the masses
2627
+	 *
2628
+	 * @return void
2629
+	 */
2630
+	protected function _add_admin_page_ajax_loading_img()
2631
+	{
2632
+		?>
2633 2633
         <div id="espresso-ajax-loading" class="ajax-loading-grey">
2634 2634
             <span class="ee-spinner ee-spin"></span><span class="hidden"><?php
2635
-                esc_html_e('loading...', 'event_espresso'); ?></span>
2635
+				esc_html_e('loading...', 'event_espresso'); ?></span>
2636 2636
         </div>
2637 2637
         <?php
2638
-    }
2638
+	}
2639 2639
 
2640 2640
 
2641
-    /**
2642
-     * add admin page overlay for modal boxes
2643
-     *
2644
-     * @return void
2645
-     */
2646
-    protected function _add_admin_page_overlay()
2647
-    {
2648
-        ?>
2641
+	/**
2642
+	 * add admin page overlay for modal boxes
2643
+	 *
2644
+	 * @return void
2645
+	 */
2646
+	protected function _add_admin_page_overlay()
2647
+	{
2648
+		?>
2649 2649
         <div id="espresso-admin-page-overlay-dv" class=""></div>
2650 2650
         <?php
2651
-    }
2652
-
2653
-
2654
-    /**
2655
-     * facade for add_meta_box
2656
-     *
2657
-     * @param string  $action        where the metabox get's displayed
2658
-     * @param string  $title         Title of Metabox (output in metabox header)
2659
-     * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2660
-     *                               instead of the one created in here.
2661
-     * @param array   $callback_args an array of args supplied for the metabox
2662
-     * @param string  $column        what metabox column
2663
-     * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2664
-     * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2665
-     *                               created but just set our own callback for wp's add_meta_box.
2666
-     * @throws DomainException
2667
-     */
2668
-    public function _add_admin_page_meta_box(
2669
-        $action,
2670
-        $title,
2671
-        $callback,
2672
-        $callback_args,
2673
-        $column = 'normal',
2674
-        $priority = 'high',
2675
-        $create_func = true
2676
-    ) {
2677
-        do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2678
-        // 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.
2679
-        if (empty($callback_args) && $create_func) {
2680
-            $callback_args = array(
2681
-                'template_path' => $this->_template_path,
2682
-                'template_args' => $this->_template_args,
2683
-            );
2684
-        }
2685
-        // 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)
2686
-        $call_back_func = $create_func
2687
-            ? static function ($post, $metabox) {
2688
-                do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2689
-                echo EEH_Template::display_template(
2690
-                    $metabox['args']['template_path'],
2691
-                    $metabox['args']['template_args'],
2692
-                    true
2693
-                );
2694
-            }
2695
-            : $callback;
2696
-        add_meta_box(
2697
-            str_replace('_', '-', $action) . '-mbox',
2698
-            $title,
2699
-            $call_back_func,
2700
-            $this->_wp_page_slug,
2701
-            $column,
2702
-            $priority,
2703
-            $callback_args
2704
-        );
2705
-    }
2706
-
2707
-
2708
-    /**
2709
-     * generates HTML wrapper for and admin details page that contains metaboxes in columns
2710
-     *
2711
-     * @throws DomainException
2712
-     * @throws EE_Error
2713
-     * @throws InvalidArgumentException
2714
-     * @throws InvalidDataTypeException
2715
-     * @throws InvalidInterfaceException
2716
-     */
2717
-    public function display_admin_page_with_metabox_columns()
2718
-    {
2719
-        $this->_template_args['post_body_content'] = $this->_template_args['admin_page_content'];
2720
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2721
-            $this->_column_template_path,
2722
-            $this->_template_args,
2723
-            true
2724
-        );
2725
-        // the final wrapper
2726
-        $this->admin_page_wrapper();
2727
-    }
2728
-
2729
-
2730
-    /**
2731
-     * generates  HTML wrapper for an admin details page
2732
-     *
2733
-     * @return void
2734
-     * @throws DomainException
2735
-     * @throws EE_Error
2736
-     * @throws InvalidArgumentException
2737
-     * @throws InvalidDataTypeException
2738
-     * @throws InvalidInterfaceException
2739
-     */
2740
-    public function display_admin_page_with_sidebar()
2741
-    {
2742
-        $this->_display_admin_page(true);
2743
-    }
2744
-
2745
-
2746
-    /**
2747
-     * generates  HTML wrapper for an admin details page (except no sidebar)
2748
-     *
2749
-     * @return void
2750
-     * @throws DomainException
2751
-     * @throws EE_Error
2752
-     * @throws InvalidArgumentException
2753
-     * @throws InvalidDataTypeException
2754
-     * @throws InvalidInterfaceException
2755
-     */
2756
-    public function display_admin_page_with_no_sidebar()
2757
-    {
2758
-        $this->_display_admin_page();
2759
-    }
2760
-
2761
-
2762
-    /**
2763
-     * generates HTML wrapper for an EE about admin page (no sidebar)
2764
-     *
2765
-     * @return void
2766
-     * @throws DomainException
2767
-     * @throws EE_Error
2768
-     * @throws InvalidArgumentException
2769
-     * @throws InvalidDataTypeException
2770
-     * @throws InvalidInterfaceException
2771
-     */
2772
-    public function display_about_admin_page()
2773
-    {
2774
-        $this->_display_admin_page(false, true);
2775
-    }
2776
-
2777
-
2778
-    /**
2779
-     * display_admin_page
2780
-     * contains the code for actually displaying an admin page
2781
-     *
2782
-     * @param boolean $sidebar true with sidebar, false without
2783
-     * @param boolean $about   use the about admin wrapper instead of the default.
2784
-     * @return void
2785
-     * @throws DomainException
2786
-     * @throws EE_Error
2787
-     * @throws InvalidArgumentException
2788
-     * @throws InvalidDataTypeException
2789
-     * @throws InvalidInterfaceException
2790
-     */
2791
-    private function _display_admin_page($sidebar = false, $about = false)
2792
-    {
2793
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2794
-        // custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2795
-        do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2796
-        // set current wp page slug - looks like: event-espresso_page_event_categories
2797
-        // keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2798
-        $this->_template_args['current_page'] = $this->_wp_page_slug;
2799
-        $this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2800
-            ? 'poststuff'
2801
-            : 'espresso-default-admin';
2802
-        $template_path = $sidebar
2803
-            ? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2804
-            : EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2805
-        if (defined('DOING_AJAX') && DOING_AJAX) {
2806
-            $template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2807
-        }
2808
-        $template_path = ! empty($this->_column_template_path)
2809
-            ? $this->_column_template_path : $template_path;
2810
-        $this->_template_args['post_body_content'] = isset($this->_template_args['admin_page_content'])
2811
-            ? $this->_template_args['admin_page_content']
2812
-            : '';
2813
-        $this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2814
-            ? $this->_template_args['before_admin_page_content']
2815
-            : '';
2816
-        $this->_template_args['after_admin_page_content'] = isset($this->_template_args['after_admin_page_content'])
2817
-            ? $this->_template_args['after_admin_page_content']
2818
-            : '';
2819
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2820
-            $template_path,
2821
-            $this->_template_args,
2822
-            true
2823
-        );
2824
-        // the final template wrapper
2825
-        $this->admin_page_wrapper($about);
2826
-    }
2827
-
2828
-
2829
-    /**
2830
-     * This is used to display caf preview pages.
2831
-     *
2832
-     * @since 4.3.2
2833
-     * @param string $utm_campaign_source what is the key used for google analytics link
2834
-     * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2835
-     *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2836
-     * @return void
2837
-     * @throws DomainException
2838
-     * @throws EE_Error
2839
-     * @throws InvalidArgumentException
2840
-     * @throws InvalidDataTypeException
2841
-     * @throws InvalidInterfaceException
2842
-     */
2843
-    public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2844
-    {
2845
-        // let's generate a default preview action button if there isn't one already present.
2846
-        $this->_labels['buttons']['buy_now'] = esc_html__(
2847
-            'Upgrade to Event Espresso 4 Right Now',
2848
-            'event_espresso'
2849
-        );
2850
-        $buy_now_url = add_query_arg(
2851
-            array(
2852
-                'ee_ver'       => 'ee4',
2853
-                'utm_source'   => 'ee4_plugin_admin',
2854
-                'utm_medium'   => 'link',
2855
-                'utm_campaign' => $utm_campaign_source,
2856
-                'utm_content'  => 'buy_now_button',
2857
-            ),
2858
-            'http://eventespresso.com/pricing/'
2859
-        );
2860
-        $this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2861
-            ? $this->get_action_link_or_button(
2862
-                '',
2863
-                'buy_now',
2864
-                array(),
2865
-                'button-primary button-large',
2866
-                $buy_now_url,
2867
-                true
2868
-            )
2869
-            : $this->_template_args['preview_action_button'];
2870
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2871
-            EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2872
-            $this->_template_args,
2873
-            true
2874
-        );
2875
-        $this->_display_admin_page($display_sidebar);
2876
-    }
2877
-
2878
-
2879
-    /**
2880
-     * display_admin_list_table_page_with_sidebar
2881
-     * generates HTML wrapper for an admin_page with list_table
2882
-     *
2883
-     * @return void
2884
-     * @throws DomainException
2885
-     * @throws EE_Error
2886
-     * @throws InvalidArgumentException
2887
-     * @throws InvalidDataTypeException
2888
-     * @throws InvalidInterfaceException
2889
-     */
2890
-    public function display_admin_list_table_page_with_sidebar()
2891
-    {
2892
-        $this->_display_admin_list_table_page(true);
2893
-    }
2894
-
2895
-
2896
-    /**
2897
-     * display_admin_list_table_page_with_no_sidebar
2898
-     * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2899
-     *
2900
-     * @return void
2901
-     * @throws DomainException
2902
-     * @throws EE_Error
2903
-     * @throws InvalidArgumentException
2904
-     * @throws InvalidDataTypeException
2905
-     * @throws InvalidInterfaceException
2906
-     */
2907
-    public function display_admin_list_table_page_with_no_sidebar()
2908
-    {
2909
-        $this->_display_admin_list_table_page();
2910
-    }
2911
-
2912
-
2913
-    /**
2914
-     * generates html wrapper for an admin_list_table page
2915
-     *
2916
-     * @param boolean $sidebar whether to display with sidebar or not.
2917
-     * @return void
2918
-     * @throws DomainException
2919
-     * @throws EE_Error
2920
-     * @throws InvalidArgumentException
2921
-     * @throws InvalidDataTypeException
2922
-     * @throws InvalidInterfaceException
2923
-     */
2924
-    private function _display_admin_list_table_page($sidebar = false)
2925
-    {
2926
-        // setup search attributes
2927
-        $this->_set_search_attributes();
2928
-        $this->_template_args['current_page'] = $this->_wp_page_slug;
2929
-        $template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2930
-        $this->_template_args['table_url'] = defined('DOING_AJAX')
2931
-            ? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2932
-            : add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
2933
-        $this->_template_args['list_table'] = $this->_list_table_object;
2934
-        $this->_template_args['current_route'] = $this->_req_action;
2935
-        $this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2936
-        $ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2937
-        if (! empty($ajax_sorting_callback)) {
2938
-            $sortable_list_table_form_fields = wp_nonce_field(
2939
-                $ajax_sorting_callback . '_nonce',
2940
-                $ajax_sorting_callback . '_nonce',
2941
-                false,
2942
-                false
2943
-            );
2944
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2945
-                                                . $this->page_slug
2946
-                                                . '" />';
2947
-            $sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2948
-                                                . $ajax_sorting_callback
2949
-                                                . '" />';
2950
-        } else {
2951
-            $sortable_list_table_form_fields = '';
2952
-        }
2953
-        $this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2954
-        $hidden_form_fields = isset($this->_template_args['list_table_hidden_fields'])
2955
-            ? $this->_template_args['list_table_hidden_fields']
2956
-            : '';
2957
-        $nonce_ref = $this->_req_action . '_nonce';
2958
-        $hidden_form_fields .= '<input type="hidden" name="'
2959
-                               . $nonce_ref
2960
-                               . '" value="'
2961
-                               . wp_create_nonce($nonce_ref)
2962
-                               . '">';
2963
-        $this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2964
-        // display message about search results?
2965
-        $this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
2966
-            ? '<p class="ee-search-results">' . sprintf(
2967
-                esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2968
-                trim($this->_req_data['s'], '%')
2969
-            ) . '</p>'
2970
-            : '';
2971
-        // filter before_list_table template arg
2972
-        $this->_template_args['before_list_table'] = apply_filters(
2973
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2974
-            $this->_template_args['before_list_table'],
2975
-            $this->page_slug,
2976
-            $this->_req_data,
2977
-            $this->_req_action
2978
-        );
2979
-        // convert to array and filter again
2980
-        // arrays are easier to inject new items in a specific location,
2981
-        // but would not be backwards compatible, so we have to add a new filter
2982
-        $this->_template_args['before_list_table'] = implode(
2983
-            " \n",
2984
-            (array) apply_filters(
2985
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2986
-                (array) $this->_template_args['before_list_table'],
2987
-                $this->page_slug,
2988
-                $this->_req_data,
2989
-                $this->_req_action
2990
-            )
2991
-        );
2992
-        // filter after_list_table template arg
2993
-        $this->_template_args['after_list_table'] = apply_filters(
2994
-            'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2995
-            $this->_template_args['after_list_table'],
2996
-            $this->page_slug,
2997
-            $this->_req_data,
2998
-            $this->_req_action
2999
-        );
3000
-        // convert to array and filter again
3001
-        // arrays are easier to inject new items in a specific location,
3002
-        // but would not be backwards compatible, so we have to add a new filter
3003
-        $this->_template_args['after_list_table'] = implode(
3004
-            " \n",
3005
-            (array) apply_filters(
3006
-                'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3007
-                (array) $this->_template_args['after_list_table'],
3008
-                $this->page_slug,
3009
-                $this->_req_data,
3010
-                $this->_req_action
3011
-            )
3012
-        );
3013
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3014
-            $template_path,
3015
-            $this->_template_args,
3016
-            true
3017
-        );
3018
-        // the final template wrapper
3019
-        if ($sidebar) {
3020
-            $this->display_admin_page_with_sidebar();
3021
-        } else {
3022
-            $this->display_admin_page_with_no_sidebar();
3023
-        }
3024
-    }
3025
-
3026
-
3027
-    /**
3028
-     * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3029
-     * html string for the legend.
3030
-     * $items are expected in an array in the following format:
3031
-     * $legend_items = array(
3032
-     *        'item_id' => array(
3033
-     *            'icon' => 'http://url_to_icon_being_described.png',
3034
-     *            'desc' => esc_html__('localized description of item');
3035
-     *        )
3036
-     * );
3037
-     *
3038
-     * @param  array $items see above for format of array
3039
-     * @return string html string of legend
3040
-     * @throws DomainException
3041
-     */
3042
-    protected function _display_legend($items)
3043
-    {
3044
-        $this->_template_args['items'] = apply_filters(
3045
-            'FHEE__EE_Admin_Page___display_legend__items',
3046
-            (array) $items,
3047
-            $this
3048
-        );
3049
-        $this->_template_args['status_change_notice'] = EEH_Template::display_template(
3050
-            EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
3051
-            [ 'context' => '__admin-legend' ],
3052
-            true
3053
-        );
3054
-        return EEH_Template::display_template(
3055
-            EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3056
-            $this->_template_args,
3057
-            true
3058
-        );
3059
-    }
3060
-
3061
-
3062
-    /**
3063
-     * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3064
-     * The returned json object is created from an array in the following format:
3065
-     * array(
3066
-     *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3067
-     *  'success' => FALSE, //(default FALSE) - contains any special success message.
3068
-     *  'notices' => '', // - contains any EE_Error formatted notices
3069
-     *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3070
-     *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3071
-     *  We're also going to include the template args with every package (so js can pick out any specific template args
3072
-     *  that might be included in here)
3073
-     * )
3074
-     * The json object is populated by whatever is set in the $_template_args property.
3075
-     *
3076
-     * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3077
-     *                                 instead of displayed.
3078
-     * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3079
-     * @return void
3080
-     * @throws EE_Error
3081
-     * @throws InvalidArgumentException
3082
-     * @throws InvalidDataTypeException
3083
-     * @throws InvalidInterfaceException
3084
-     */
3085
-    protected function _return_json($sticky_notices = false, $notices_arguments = array())
3086
-    {
3087
-        // make sure any EE_Error notices have been handled.
3088
-        $this->_process_notices($notices_arguments, true, $sticky_notices);
3089
-        $data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
3090
-        unset($this->_template_args['data']);
3091
-        $json = array(
3092
-            'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3093
-            'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3094
-            'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3095
-            'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3096
-            'notices'   => EE_Error::get_notices(),
3097
-            'content'   => isset($this->_template_args['admin_page_content'])
3098
-                ? $this->_template_args['admin_page_content'] : '',
3099
-            'data'      => array_merge($data, array('template_args' => $this->_template_args)),
3100
-            'isEEajax'  => true
3101
-            // special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3102
-        );
3103
-        // make sure there are no php errors or headers_sent.  Then we can set correct json header.
3104
-        if (null === error_get_last() || ! headers_sent()) {
3105
-            header('Content-Type: application/json; charset=UTF-8');
3106
-        }
3107
-        echo wp_json_encode($json);
3108
-        exit();
3109
-    }
3110
-
3111
-
3112
-    /**
3113
-     * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3114
-     *
3115
-     * @return void
3116
-     * @throws EE_Error
3117
-     * @throws InvalidArgumentException
3118
-     * @throws InvalidDataTypeException
3119
-     * @throws InvalidInterfaceException
3120
-     */
3121
-    public function return_json()
3122
-    {
3123
-        if (defined('DOING_AJAX') && DOING_AJAX) {
3124
-            $this->_return_json();
3125
-        } else {
3126
-            throw new EE_Error(
3127
-                sprintf(
3128
-                    esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3129
-                    __FUNCTION__
3130
-                )
3131
-            );
3132
-        }
3133
-    }
3134
-
3135
-
3136
-    /**
3137
-     * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3138
-     * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3139
-     *
3140
-     * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3141
-     */
3142
-    public function set_hook_object(EE_Admin_Hooks $hook_obj)
3143
-    {
3144
-        $this->_hook_obj = $hook_obj;
3145
-    }
3146
-
3147
-
3148
-    /**
3149
-     *        generates  HTML wrapper with Tabbed nav for an admin page
3150
-     *
3151
-     * @param boolean $about whether to use the special about page wrapper or default.
3152
-     * @return void
3153
-     * @throws DomainException
3154
-     * @throws EE_Error
3155
-     * @throws InvalidArgumentException
3156
-     * @throws InvalidDataTypeException
3157
-     * @throws InvalidInterfaceException
3158
-     */
3159
-    public function admin_page_wrapper($about = false)
3160
-    {
3161
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3162
-        $this->_nav_tabs = $this->_get_main_nav_tabs();
3163
-        $this->_template_args['nav_tabs'] = $this->_nav_tabs;
3164
-        $this->_template_args['admin_page_title'] = $this->_admin_page_title;
3165
-        $this->_template_args['before_admin_page_content'] = apply_filters(
3166
-            "FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3167
-            isset($this->_template_args['before_admin_page_content'])
3168
-                ? $this->_template_args['before_admin_page_content']
3169
-                : ''
3170
-        );
3171
-        $this->_template_args['after_admin_page_content'] = apply_filters(
3172
-            "FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3173
-            isset($this->_template_args['after_admin_page_content'])
3174
-                ? $this->_template_args['after_admin_page_content']
3175
-                : ''
3176
-        );
3177
-        $this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3178
-        // load settings page wrapper template
3179
-        $template_path = ! defined('DOING_AJAX')
3180
-            ? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3181
-            : EE_ADMIN_TEMPLATE
3182
-              . 'admin_wrapper_ajax.template.php';
3183
-        // about page?
3184
-        $template_path = $about
3185
-            ? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3186
-            : $template_path;
3187
-        if (defined('DOING_AJAX')) {
3188
-            $this->_template_args['admin_page_content'] = EEH_Template::display_template(
3189
-                $template_path,
3190
-                $this->_template_args,
3191
-                true
3192
-            );
3193
-            $this->_return_json();
3194
-        } else {
3195
-            EEH_Template::display_template($template_path, $this->_template_args);
3196
-        }
3197
-    }
3198
-
3199
-
3200
-    /**
3201
-     * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3202
-     *
3203
-     * @return string html
3204
-     * @throws EE_Error
3205
-     */
3206
-    protected function _get_main_nav_tabs()
3207
-    {
3208
-        // let's generate the html using the EEH_Tabbed_Content helper.
3209
-        // We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3210
-        // (rather than setting in the page_routes array)
3211
-        return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3212
-    }
3213
-
3214
-
3215
-    /**
3216
-     *        sort nav tabs
3217
-     *
3218
-     * @param $a
3219
-     * @param $b
3220
-     * @return int
3221
-     */
3222
-    private function _sort_nav_tabs($a, $b)
3223
-    {
3224
-        if ($a['order'] === $b['order']) {
3225
-            return 0;
3226
-        }
3227
-        return ($a['order'] < $b['order']) ? -1 : 1;
3228
-    }
3229
-
3230
-
3231
-    /**
3232
-     *    generates HTML for the forms used on admin pages
3233
-     *
3234
-     * @param    array $input_vars - array of input field details
3235
-     * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to
3236
-     *                             use)
3237
-     * @param bool     $id
3238
-     * @return string
3239
-     * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3240
-     * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3241
-     */
3242
-    protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
3243
-    {
3244
-        return $generator === 'string'
3245
-            ? EEH_Form_Fields::get_form_fields($input_vars, $id)
3246
-            : EEH_Form_Fields::get_form_fields_array($input_vars);
3247
-    }
3248
-
3249
-
3250
-    /**
3251
-     * generates the "Save" and "Save & Close" buttons for edit forms
3252
-     *
3253
-     * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3254
-     *                                   Close" button.
3255
-     * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3256
-     *                                   'Save', [1] => 'save & close')
3257
-     * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3258
-     *                                   via the "name" value in the button).  We can also use this to just dump
3259
-     *                                   default actions by submitting some other value.
3260
-     * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3261
-     *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3262
-     *                                   close (normal form handling).
3263
-     */
3264
-    protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
3265
-    {
3266
-        // make sure $text and $actions are in an array
3267
-        $text = (array) $text;
3268
-        $actions = (array) $actions;
3269
-        $referrer_url = empty($referrer)
3270
-            ? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3271
-              . $_SERVER['REQUEST_URI']
3272
-              . '" />'
3273
-            : '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3274
-              . $referrer
3275
-              . '" />';
3276
-        $button_text = ! empty($text)
3277
-            ? $text
3278
-            : array(
3279
-                esc_html__('Save', 'event_espresso'),
3280
-                esc_html__('Save and Close', 'event_espresso'),
3281
-            );
3282
-        $default_names = array('save', 'save_and_close');
3283
-        // add in a hidden index for the current page (so save and close redirects properly)
3284
-        $this->_template_args['save_buttons'] = $referrer_url;
3285
-        foreach ($button_text as $key => $button) {
3286
-            $ref = $default_names[ $key ];
3287
-            $this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3288
-                                                     . $ref
3289
-                                                     . '" value="'
3290
-                                                     . $button
3291
-                                                     . '" name="'
3292
-                                                     . (! empty($actions) ? $actions[ $key ] : $ref)
3293
-                                                     . '" id="'
3294
-                                                     . $this->_current_view . '_' . $ref
3295
-                                                     . '" />';
3296
-            if (! $both) {
3297
-                break;
3298
-            }
3299
-        }
3300
-    }
3301
-
3302
-
3303
-    /**
3304
-     * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3305
-     *
3306
-     * @see   $this->_set_add_edit_form_tags() for details on params
3307
-     * @since 4.6.0
3308
-     * @param string $route
3309
-     * @param array  $additional_hidden_fields
3310
-     */
3311
-    public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3312
-    {
3313
-        $this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3314
-    }
3315
-
3316
-
3317
-    /**
3318
-     * set form open and close tags on add/edit pages.
3319
-     *
3320
-     * @param string $route                    the route you want the form to direct to
3321
-     * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3322
-     * @return void
3323
-     */
3324
-    protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3325
-    {
3326
-        if (empty($route)) {
3327
-            $user_msg = esc_html__(
3328
-                'An error occurred. No action was set for this page\'s form.',
3329
-                'event_espresso'
3330
-            );
3331
-            $dev_msg = $user_msg . "\n"
3332
-                       . sprintf(
3333
-                           esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3334
-                           __FUNCTION__,
3335
-                           EE_Admin_Page::class
3336
-                       );
3337
-            EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3338
-        }
3339
-        // open form
3340
-        $this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3341
-                                                             . $this->_admin_base_url
3342
-                                                             . '" id="'
3343
-                                                             . $route
3344
-                                                             . '_event_form" >';
3345
-        // add nonce
3346
-        $nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3347
-        $this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3348
-        // add REQUIRED form action
3349
-        $hidden_fields = array(
3350
-            'action' => array('type' => 'hidden', 'value' => $route),
3351
-        );
3352
-        // merge arrays
3353
-        $hidden_fields = is_array($additional_hidden_fields)
3354
-            ? array_merge($hidden_fields, $additional_hidden_fields)
3355
-            : $hidden_fields;
3356
-        // generate form fields
3357
-        $form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3358
-        // add fields to form
3359
-        foreach ((array) $form_fields as $field_name => $form_field) {
3360
-            $this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3361
-        }
3362
-        // close form
3363
-        $this->_template_args['after_admin_page_content'] = '</form>';
3364
-    }
3365
-
3366
-
3367
-    /**
3368
-     * Public Wrapper for _redirect_after_action() method since its
3369
-     * discovered it would be useful for external code to have access.
3370
-     *
3371
-     * @param bool   $success
3372
-     * @param string $what
3373
-     * @param string $action_desc
3374
-     * @param array  $query_args
3375
-     * @param bool   $override_overwrite
3376
-     * @throws EE_Error
3377
-     * @throws InvalidArgumentException
3378
-     * @throws InvalidDataTypeException
3379
-     * @throws InvalidInterfaceException
3380
-     * @see   EE_Admin_Page::_redirect_after_action() for params.
3381
-     * @since 4.5.0
3382
-     */
3383
-    public function redirect_after_action(
3384
-        $success = false,
3385
-        $what = 'item',
3386
-        $action_desc = 'processed',
3387
-        $query_args = array(),
3388
-        $override_overwrite = false
3389
-    ) {
3390
-        $this->_redirect_after_action(
3391
-            $success,
3392
-            $what,
3393
-            $action_desc,
3394
-            $query_args,
3395
-            $override_overwrite
3396
-        );
3397
-    }
3398
-
3399
-
3400
-    /**
3401
-     * Helper method for merging existing request data with the returned redirect url.
3402
-     *
3403
-     * This is typically used for redirects after an action so that if the original view was a filtered view those
3404
-     * filters are still applied.
3405
-     *
3406
-     * @param array $new_route_data
3407
-     * @return array
3408
-     */
3409
-    protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3410
-    {
3411
-        foreach ($this->_req_data as $ref => $value) {
3412
-            // unset nonces
3413
-            if (strpos($ref, 'nonce') !== false) {
3414
-                unset($this->_req_data[ $ref ]);
3415
-                continue;
3416
-            }
3417
-            // urlencode values.
3418
-            $value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3419
-            $this->_req_data[ $ref ] = $value;
3420
-        }
3421
-        return array_merge($this->_req_data, $new_route_data);
3422
-    }
3423
-
3424
-
3425
-    /**
3426
-     *    _redirect_after_action
3427
-     *
3428
-     * @param int    $success            - whether success was for two or more records, or just one, or none
3429
-     * @param string $what               - what the action was performed on
3430
-     * @param string $action_desc        - what was done ie: updated, deleted, etc
3431
-     * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3432
-     *                                   action is completed
3433
-     * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3434
-     *                                   override this so that they show.
3435
-     * @return void
3436
-     * @throws EE_Error
3437
-     * @throws InvalidArgumentException
3438
-     * @throws InvalidDataTypeException
3439
-     * @throws InvalidInterfaceException
3440
-     */
3441
-    protected function _redirect_after_action(
3442
-        $success = 0,
3443
-        $what = 'item',
3444
-        $action_desc = 'processed',
3445
-        $query_args = array(),
3446
-        $override_overwrite = false
3447
-    ) {
3448
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3449
-        // class name for actions/filters.
3450
-        $classname = get_class($this);
3451
-        // set redirect url.
3452
-        // Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3453
-        // otherwise we go with whatever is set as the _admin_base_url
3454
-        $redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3455
-        $notices = EE_Error::get_notices(false);
3456
-        // overwrite default success messages //BUT ONLY if overwrite not overridden
3457
-        if (! $override_overwrite || ! empty($notices['errors'])) {
3458
-            EE_Error::overwrite_success();
3459
-        }
3460
-        if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3461
-            // how many records affected ? more than one record ? or just one ?
3462
-            if ($success > 1) {
3463
-                // set plural msg
3464
-                EE_Error::add_success(
3465
-                    sprintf(
3466
-                        esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3467
-                        $what,
3468
-                        $action_desc
3469
-                    ),
3470
-                    __FILE__,
3471
-                    __FUNCTION__,
3472
-                    __LINE__
3473
-                );
3474
-            } elseif ($success === 1) {
3475
-                // set singular msg
3476
-                EE_Error::add_success(
3477
-                    sprintf(
3478
-                        esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3479
-                        $what,
3480
-                        $action_desc
3481
-                    ),
3482
-                    __FILE__,
3483
-                    __FUNCTION__,
3484
-                    __LINE__
3485
-                );
3486
-            }
3487
-        }
3488
-        // check that $query_args isn't something crazy
3489
-        if (! is_array($query_args)) {
3490
-            $query_args = array();
3491
-        }
3492
-        /**
3493
-         * Allow injecting actions before the query_args are modified for possible different
3494
-         * redirections on save and close actions
3495
-         *
3496
-         * @since 4.2.0
3497
-         * @param array $query_args       The original query_args array coming into the
3498
-         *                                method.
3499
-         */
3500
-        do_action(
3501
-            "AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3502
-            $query_args
3503
-        );
3504
-        // calculate where we're going (if we have a "save and close" button pushed)
3505
-        if (isset($this->_req_data['save_and_close'], $this->_req_data['save_and_close_referrer'])) {
3506
-            // even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3507
-            $parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
3508
-            // regenerate query args array from referrer URL
3509
-            parse_str($parsed_url['query'], $query_args);
3510
-            // correct page and action will be in the query args now
3511
-            $redirect_url = admin_url('admin.php');
3512
-        }
3513
-        // merge any default query_args set in _default_route_query_args property
3514
-        if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3515
-            $args_to_merge = array();
3516
-            foreach ($this->_default_route_query_args as $query_param => $query_value) {
3517
-                // is there a wp_referer array in our _default_route_query_args property?
3518
-                if ($query_param === 'wp_referer') {
3519
-                    $query_value = (array) $query_value;
3520
-                    foreach ($query_value as $reference => $value) {
3521
-                        if (strpos($reference, 'nonce') !== false) {
3522
-                            continue;
3523
-                        }
3524
-                        // finally we will override any arguments in the referer with
3525
-                        // what might be set on the _default_route_query_args array.
3526
-                        if (isset($this->_default_route_query_args[ $reference ])) {
3527
-                            $args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3528
-                        } else {
3529
-                            $args_to_merge[ $reference ] = urlencode($value);
3530
-                        }
3531
-                    }
3532
-                    continue;
3533
-                }
3534
-                $args_to_merge[ $query_param ] = $query_value;
3535
-            }
3536
-            // now let's merge these arguments but override with what was specifically sent in to the
3537
-            // redirect.
3538
-            $query_args = array_merge($args_to_merge, $query_args);
3539
-        }
3540
-        $this->_process_notices($query_args);
3541
-        // generate redirect url
3542
-        // if redirecting to anything other than the main page, add a nonce
3543
-        if (isset($query_args['action'])) {
3544
-            // manually generate wp_nonce and merge that with the query vars
3545
-            // becuz the wp_nonce_url function wrecks havoc on some vars
3546
-            $query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3547
-        }
3548
-        // we're adding some hooks and filters in here for processing any things just before redirects
3549
-        // (example: an admin page has done an insert or update and we want to run something after that).
3550
-        do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3551
-        $redirect_url = apply_filters(
3552
-            'FHEE_redirect_' . $classname . $this->_req_action,
3553
-            EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3554
-            $query_args
3555
-        );
3556
-        // check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3557
-        if (defined('DOING_AJAX')) {
3558
-            $default_data = array(
3559
-                'close'        => true,
3560
-                'redirect_url' => $redirect_url,
3561
-                'where'        => 'main',
3562
-                'what'         => 'append',
3563
-            );
3564
-            $this->_template_args['success'] = $success;
3565
-            $this->_template_args['data'] = ! empty($this->_template_args['data']) ? array_merge(
3566
-                $default_data,
3567
-                $this->_template_args['data']
3568
-            ) : $default_data;
3569
-            $this->_return_json();
3570
-        }
3571
-        wp_safe_redirect($redirect_url);
3572
-        exit();
3573
-    }
3574
-
3575
-
3576
-    /**
3577
-     * process any notices before redirecting (or returning ajax request)
3578
-     * This method sets the $this->_template_args['notices'] attribute;
3579
-     *
3580
-     * @param array $query_args         any query args that need to be used for notice transient ('action')
3581
-     * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3582
-     *                                  page_routes haven't been defined yet.
3583
-     * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3584
-     *                                  still save a transient for the notice.
3585
-     * @return void
3586
-     * @throws EE_Error
3587
-     * @throws InvalidArgumentException
3588
-     * @throws InvalidDataTypeException
3589
-     * @throws InvalidInterfaceException
3590
-     */
3591
-    protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
3592
-    {
3593
-        // first let's set individual error properties if doing_ajax and the properties aren't already set.
3594
-        if (defined('DOING_AJAX') && DOING_AJAX) {
3595
-            $notices = EE_Error::get_notices(false);
3596
-            if (empty($this->_template_args['success'])) {
3597
-                $this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3598
-            }
3599
-            if (empty($this->_template_args['errors'])) {
3600
-                $this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3601
-            }
3602
-            if (empty($this->_template_args['attention'])) {
3603
-                $this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3604
-            }
3605
-        }
3606
-        $this->_template_args['notices'] = EE_Error::get_notices();
3607
-        // IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3608
-        if (! defined('DOING_AJAX') || $sticky_notices) {
3609
-            $route = isset($query_args['action']) ? $query_args['action'] : 'default';
3610
-            $this->_add_transient(
3611
-                $route,
3612
-                $this->_template_args['notices'],
3613
-                true,
3614
-                $skip_route_verify
3615
-            );
3616
-        }
3617
-    }
3618
-
3619
-
3620
-    /**
3621
-     * get_action_link_or_button
3622
-     * returns the button html for adding, editing, or deleting an item (depending on given type)
3623
-     *
3624
-     * @param string $action        use this to indicate which action the url is generated with.
3625
-     * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3626
-     *                              property.
3627
-     * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3628
-     * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3629
-     * @param string $base_url      If this is not provided
3630
-     *                              the _admin_base_url will be used as the default for the button base_url.
3631
-     *                              Otherwise this value will be used.
3632
-     * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3633
-     * @return string
3634
-     * @throws InvalidArgumentException
3635
-     * @throws InvalidInterfaceException
3636
-     * @throws InvalidDataTypeException
3637
-     * @throws EE_Error
3638
-     */
3639
-    public function get_action_link_or_button(
3640
-        $action,
3641
-        $type = 'add',
3642
-        $extra_request = array(),
3643
-        $class = 'button-primary',
3644
-        $base_url = '',
3645
-        $exclude_nonce = false
3646
-    ) {
3647
-        // first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3648
-        if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3649
-            throw new EE_Error(
3650
-                sprintf(
3651
-                    esc_html__(
3652
-                        'There is no page route for given action for the button.  This action was given: %s',
3653
-                        'event_espresso'
3654
-                    ),
3655
-                    $action
3656
-                )
3657
-            );
3658
-        }
3659
-        if (! isset($this->_labels['buttons'][ $type ])) {
3660
-            throw new EE_Error(
3661
-                sprintf(
3662
-                    __(
3663
-                        'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3664
-                        'event_espresso'
3665
-                    ),
3666
-                    $type
3667
-                )
3668
-            );
3669
-        }
3670
-        // finally check user access for this button.
3671
-        $has_access = $this->check_user_access($action, true);
3672
-        if (! $has_access) {
3673
-            return '';
3674
-        }
3675
-        $_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
3676
-        $query_args = array(
3677
-            'action' => $action,
3678
-        );
3679
-        // merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3680
-        if (! empty($extra_request)) {
3681
-            $query_args = array_merge($extra_request, $query_args);
3682
-        }
3683
-        $url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3684
-        return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3685
-    }
3686
-
3687
-
3688
-    /**
3689
-     * _per_page_screen_option
3690
-     * Utility function for adding in a per_page_option in the screen_options_dropdown.
3691
-     *
3692
-     * @return void
3693
-     * @throws InvalidArgumentException
3694
-     * @throws InvalidInterfaceException
3695
-     * @throws InvalidDataTypeException
3696
-     */
3697
-    protected function _per_page_screen_option()
3698
-    {
3699
-        $option = 'per_page';
3700
-        $args = array(
3701
-            'label'   => apply_filters(
3702
-                'FHEE__EE_Admin_Page___per_page_screen_options___label',
3703
-                $this->_admin_page_title,
3704
-                $this
3705
-            ),
3706
-            'default' => (int) apply_filters(
3707
-                'FHEE__EE_Admin_Page___per_page_screen_options__default',
3708
-                20
3709
-            ),
3710
-            'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3711
-        );
3712
-        // ONLY add the screen option if the user has access to it.
3713
-        if ($this->check_user_access($this->_current_view, true)) {
3714
-            add_screen_option($option, $args);
3715
-        }
3716
-    }
3717
-
3718
-
3719
-    /**
3720
-     * set_per_page_screen_option
3721
-     * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3722
-     * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3723
-     * admin_menu.
3724
-     *
3725
-     * @return void
3726
-     */
3727
-    private function _set_per_page_screen_options()
3728
-    {
3729
-        if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3730
-            check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3731
-            if (! $user = wp_get_current_user()) {
3732
-                return;
3733
-            }
3734
-            $option = $_POST['wp_screen_options']['option'];
3735
-            $value = $_POST['wp_screen_options']['value'];
3736
-            if ($option !== sanitize_key($option)) {
3737
-                return;
3738
-            }
3739
-            $map_option = $option;
3740
-            $option = str_replace('-', '_', $option);
3741
-            switch ($map_option) {
3742
-                case $this->_current_page . '_' . $this->_current_view . '_per_page':
3743
-                    $value = (int) $value;
3744
-                    $max_value = apply_filters(
3745
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3746
-                        999,
3747
-                        $this->_current_page,
3748
-                        $this->_current_view
3749
-                    );
3750
-                    if ($value < 1) {
3751
-                        return;
3752
-                    }
3753
-                    $value = min($value, $max_value);
3754
-                    break;
3755
-                default:
3756
-                    $value = apply_filters(
3757
-                        'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3758
-                        false,
3759
-                        $option,
3760
-                        $value
3761
-                    );
3762
-                    if (false === $value) {
3763
-                        return;
3764
-                    }
3765
-                    break;
3766
-            }
3767
-            update_user_meta($user->ID, $option, $value);
3768
-            wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3769
-            exit;
3770
-        }
3771
-    }
3772
-
3773
-
3774
-    /**
3775
-     * This just allows for setting the $_template_args property if it needs to be set outside the object
3776
-     *
3777
-     * @param array $data array that will be assigned to template args.
3778
-     */
3779
-    public function set_template_args($data)
3780
-    {
3781
-        $this->_template_args = array_merge($this->_template_args, (array) $data);
3782
-    }
3783
-
3784
-
3785
-    /**
3786
-     * This makes available the WP transient system for temporarily moving data between routes
3787
-     *
3788
-     * @param string $route             the route that should receive the transient
3789
-     * @param array  $data              the data that gets sent
3790
-     * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3791
-     *                                  normal route transient.
3792
-     * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3793
-     *                                  when we are adding a transient before page_routes have been defined.
3794
-     * @return void
3795
-     * @throws EE_Error
3796
-     */
3797
-    protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3798
-    {
3799
-        $user_id = get_current_user_id();
3800
-        if (! $skip_route_verify) {
3801
-            $this->_verify_route($route);
3802
-        }
3803
-        // now let's set the string for what kind of transient we're setting
3804
-        $transient = $notices
3805
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3806
-            : 'rte_tx_' . $route . '_' . $user_id;
3807
-        $data = $notices ? array('notices' => $data) : $data;
3808
-        // is there already a transient for this route?  If there is then let's ADD to that transient
3809
-        $existing = is_multisite() && is_network_admin()
3810
-            ? get_site_transient($transient)
3811
-            : get_transient($transient);
3812
-        if ($existing) {
3813
-            $data = array_merge((array) $data, (array) $existing);
3814
-        }
3815
-        if (is_multisite() && is_network_admin()) {
3816
-            set_site_transient($transient, $data, 8);
3817
-        } else {
3818
-            set_transient($transient, $data, 8);
3819
-        }
3820
-    }
3821
-
3822
-
3823
-    /**
3824
-     * this retrieves the temporary transient that has been set for moving data between routes.
3825
-     *
3826
-     * @param bool   $notices true we get notices transient. False we just return normal route transient
3827
-     * @param string $route
3828
-     * @return mixed data
3829
-     */
3830
-    protected function _get_transient($notices = false, $route = '')
3831
-    {
3832
-        $user_id = get_current_user_id();
3833
-        $route = ! $route ? $this->_req_action : $route;
3834
-        $transient = $notices
3835
-            ? 'ee_rte_n_tx_' . $route . '_' . $user_id
3836
-            : 'rte_tx_' . $route . '_' . $user_id;
3837
-        $data = is_multisite() && is_network_admin()
3838
-            ? get_site_transient($transient)
3839
-            : get_transient($transient);
3840
-        // delete transient after retrieval (just in case it hasn't expired);
3841
-        if (is_multisite() && is_network_admin()) {
3842
-            delete_site_transient($transient);
3843
-        } else {
3844
-            delete_transient($transient);
3845
-        }
3846
-        return $notices && isset($data['notices']) ? $data['notices'] : $data;
3847
-    }
3848
-
3849
-
3850
-    /**
3851
-     * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3852
-     * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3853
-     * default route callback on the EE_Admin page you want it run.)
3854
-     *
3855
-     * @return void
3856
-     */
3857
-    protected function _transient_garbage_collection()
3858
-    {
3859
-        global $wpdb;
3860
-        // retrieve all existing transients
3861
-        $query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3862
-        if ($results = $wpdb->get_results($query)) {
3863
-            foreach ($results as $result) {
3864
-                $transient = str_replace('_transient_', '', $result->option_name);
3865
-                get_transient($transient);
3866
-                if (is_multisite() && is_network_admin()) {
3867
-                    get_site_transient($transient);
3868
-                }
3869
-            }
3870
-        }
3871
-    }
3872
-
3873
-
3874
-    /**
3875
-     * get_view
3876
-     *
3877
-     * @return string content of _view property
3878
-     */
3879
-    public function get_view()
3880
-    {
3881
-        return $this->_view;
3882
-    }
3883
-
3884
-
3885
-    /**
3886
-     * getter for the protected $_views property
3887
-     *
3888
-     * @return array
3889
-     */
3890
-    public function get_views()
3891
-    {
3892
-        return $this->_views;
3893
-    }
3894
-
3895
-
3896
-    /**
3897
-     * get_current_page
3898
-     *
3899
-     * @return string _current_page property value
3900
-     */
3901
-    public function get_current_page()
3902
-    {
3903
-        return $this->_current_page;
3904
-    }
3905
-
3906
-
3907
-    /**
3908
-     * get_current_view
3909
-     *
3910
-     * @return string _current_view property value
3911
-     */
3912
-    public function get_current_view()
3913
-    {
3914
-        return $this->_current_view;
3915
-    }
3916
-
3917
-
3918
-    /**
3919
-     * get_current_screen
3920
-     *
3921
-     * @return object The current WP_Screen object
3922
-     */
3923
-    public function get_current_screen()
3924
-    {
3925
-        return $this->_current_screen;
3926
-    }
3927
-
3928
-
3929
-    /**
3930
-     * get_current_page_view_url
3931
-     *
3932
-     * @return string This returns the url for the current_page_view.
3933
-     */
3934
-    public function get_current_page_view_url()
3935
-    {
3936
-        return $this->_current_page_view_url;
3937
-    }
3938
-
3939
-
3940
-    /**
3941
-     * just returns the _req_data property
3942
-     *
3943
-     * @return array
3944
-     */
3945
-    public function get_request_data()
3946
-    {
3947
-        return $this->_req_data;
3948
-    }
3949
-
3950
-
3951
-    /**
3952
-     * returns the _req_data protected property
3953
-     *
3954
-     * @return string
3955
-     */
3956
-    public function get_req_action()
3957
-    {
3958
-        return $this->_req_action;
3959
-    }
3960
-
3961
-
3962
-    /**
3963
-     * @return bool  value of $_is_caf property
3964
-     */
3965
-    public function is_caf()
3966
-    {
3967
-        return $this->_is_caf;
3968
-    }
3969
-
3970
-
3971
-    /**
3972
-     * @return mixed
3973
-     */
3974
-    public function default_espresso_metaboxes()
3975
-    {
3976
-        return $this->_default_espresso_metaboxes;
3977
-    }
3978
-
3979
-
3980
-    /**
3981
-     * @return mixed
3982
-     */
3983
-    public function admin_base_url()
3984
-    {
3985
-        return $this->_admin_base_url;
3986
-    }
3987
-
3988
-
3989
-    /**
3990
-     * @return mixed
3991
-     */
3992
-    public function wp_page_slug()
3993
-    {
3994
-        return $this->_wp_page_slug;
3995
-    }
3996
-
3997
-
3998
-    /**
3999
-     * updates  espresso configuration settings
4000
-     *
4001
-     * @param string                   $tab
4002
-     * @param EE_Config_Base|EE_Config $config
4003
-     * @param string                   $file file where error occurred
4004
-     * @param string                   $func function  where error occurred
4005
-     * @param string                   $line line no where error occurred
4006
-     * @return boolean
4007
-     */
4008
-    protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4009
-    {
4010
-        // remove any options that are NOT going to be saved with the config settings.
4011
-        if (isset($config->core->ee_ueip_optin)) {
4012
-            // TODO: remove the following two lines and make sure values are migrated from 3.1
4013
-            update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4014
-            update_option('ee_ueip_has_notified', true);
4015
-        }
4016
-        // and save it (note we're also doing the network save here)
4017
-        $net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4018
-        $config_saved = EE_Config::instance()->update_espresso_config(false, false);
4019
-        if ($config_saved && $net_saved) {
4020
-            EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4021
-            return true;
4022
-        }
4023
-        EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4024
-        return false;
4025
-    }
4026
-
4027
-
4028
-    /**
4029
-     * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4030
-     *
4031
-     * @return array
4032
-     */
4033
-    public function get_yes_no_values()
4034
-    {
4035
-        return $this->_yes_no_values;
4036
-    }
4037
-
4038
-
4039
-    /**
4040
-     * @return string
4041
-     * @throws ReflectionException
4042
-     * @since $VID:$
4043
-     */
4044
-    protected function _get_dir()
4045
-    {
4046
-        $reflector = new ReflectionClass(get_class($this));
4047
-        return dirname($reflector->getFileName());
4048
-    }
4049
-
4050
-
4051
-    /**
4052
-     * A helper for getting a "next link".
4053
-     *
4054
-     * @param string $url   The url to link to
4055
-     * @param string $class The class to use.
4056
-     * @return string
4057
-     */
4058
-    protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4059
-    {
4060
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4061
-    }
4062
-
4063
-
4064
-    /**
4065
-     * A helper for getting a "previous link".
4066
-     *
4067
-     * @param string $url   The url to link to
4068
-     * @param string $class The class to use.
4069
-     * @return string
4070
-     */
4071
-    protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4072
-    {
4073
-        return '<a class="' . $class . '" href="' . $url . '"></a>';
4074
-    }
4075
-
4076
-
4077
-
4078
-
4079
-
4080
-
4081
-
4082
-    // below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4083
-
4084
-
4085
-    /**
4086
-     * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4087
-     * 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
4088
-     * _req_data array.
4089
-     *
4090
-     * @return bool success/fail
4091
-     * @throws EE_Error
4092
-     * @throws InvalidArgumentException
4093
-     * @throws ReflectionException
4094
-     * @throws InvalidDataTypeException
4095
-     * @throws InvalidInterfaceException
4096
-     */
4097
-    protected function _process_resend_registration()
4098
-    {
4099
-        $this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4100
-        do_action(
4101
-            'AHEE__EE_Admin_Page___process_resend_registration',
4102
-            $this->_template_args['success'],
4103
-            $this->_req_data
4104
-        );
4105
-        return $this->_template_args['success'];
4106
-    }
4107
-
4108
-
4109
-    /**
4110
-     * This automatically processes any payment message notifications when manual payment has been applied.
4111
-     *
4112
-     * @param EE_Payment $payment
4113
-     * @return bool success/fail
4114
-     */
4115
-    protected function _process_payment_notification(EE_Payment $payment)
4116
-    {
4117
-        add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4118
-        do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4119
-        $this->_template_args['success'] = apply_filters(
4120
-            'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4121
-            false,
4122
-            $payment
4123
-        );
4124
-        return $this->_template_args['success'];
4125
-    }
2651
+	}
2652
+
2653
+
2654
+	/**
2655
+	 * facade for add_meta_box
2656
+	 *
2657
+	 * @param string  $action        where the metabox get's displayed
2658
+	 * @param string  $title         Title of Metabox (output in metabox header)
2659
+	 * @param string  $callback      If not empty and $create_fun is set to false then we'll use a custom callback
2660
+	 *                               instead of the one created in here.
2661
+	 * @param array   $callback_args an array of args supplied for the metabox
2662
+	 * @param string  $column        what metabox column
2663
+	 * @param string  $priority      give this metabox a priority (using accepted priorities for wp meta boxes)
2664
+	 * @param boolean $create_func   default is true.  Basically we can say we don't WANT to have the runtime function
2665
+	 *                               created but just set our own callback for wp's add_meta_box.
2666
+	 * @throws DomainException
2667
+	 */
2668
+	public function _add_admin_page_meta_box(
2669
+		$action,
2670
+		$title,
2671
+		$callback,
2672
+		$callback_args,
2673
+		$column = 'normal',
2674
+		$priority = 'high',
2675
+		$create_func = true
2676
+	) {
2677
+		do_action('AHEE_log', __FILE__, __FUNCTION__, $callback);
2678
+		// 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.
2679
+		if (empty($callback_args) && $create_func) {
2680
+			$callback_args = array(
2681
+				'template_path' => $this->_template_path,
2682
+				'template_args' => $this->_template_args,
2683
+			);
2684
+		}
2685
+		// 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)
2686
+		$call_back_func = $create_func
2687
+			? static function ($post, $metabox) {
2688
+				do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2689
+				echo EEH_Template::display_template(
2690
+					$metabox['args']['template_path'],
2691
+					$metabox['args']['template_args'],
2692
+					true
2693
+				);
2694
+			}
2695
+			: $callback;
2696
+		add_meta_box(
2697
+			str_replace('_', '-', $action) . '-mbox',
2698
+			$title,
2699
+			$call_back_func,
2700
+			$this->_wp_page_slug,
2701
+			$column,
2702
+			$priority,
2703
+			$callback_args
2704
+		);
2705
+	}
2706
+
2707
+
2708
+	/**
2709
+	 * generates HTML wrapper for and admin details page that contains metaboxes in columns
2710
+	 *
2711
+	 * @throws DomainException
2712
+	 * @throws EE_Error
2713
+	 * @throws InvalidArgumentException
2714
+	 * @throws InvalidDataTypeException
2715
+	 * @throws InvalidInterfaceException
2716
+	 */
2717
+	public function display_admin_page_with_metabox_columns()
2718
+	{
2719
+		$this->_template_args['post_body_content'] = $this->_template_args['admin_page_content'];
2720
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2721
+			$this->_column_template_path,
2722
+			$this->_template_args,
2723
+			true
2724
+		);
2725
+		// the final wrapper
2726
+		$this->admin_page_wrapper();
2727
+	}
2728
+
2729
+
2730
+	/**
2731
+	 * generates  HTML wrapper for an admin details page
2732
+	 *
2733
+	 * @return void
2734
+	 * @throws DomainException
2735
+	 * @throws EE_Error
2736
+	 * @throws InvalidArgumentException
2737
+	 * @throws InvalidDataTypeException
2738
+	 * @throws InvalidInterfaceException
2739
+	 */
2740
+	public function display_admin_page_with_sidebar()
2741
+	{
2742
+		$this->_display_admin_page(true);
2743
+	}
2744
+
2745
+
2746
+	/**
2747
+	 * generates  HTML wrapper for an admin details page (except no sidebar)
2748
+	 *
2749
+	 * @return void
2750
+	 * @throws DomainException
2751
+	 * @throws EE_Error
2752
+	 * @throws InvalidArgumentException
2753
+	 * @throws InvalidDataTypeException
2754
+	 * @throws InvalidInterfaceException
2755
+	 */
2756
+	public function display_admin_page_with_no_sidebar()
2757
+	{
2758
+		$this->_display_admin_page();
2759
+	}
2760
+
2761
+
2762
+	/**
2763
+	 * generates HTML wrapper for an EE about admin page (no sidebar)
2764
+	 *
2765
+	 * @return void
2766
+	 * @throws DomainException
2767
+	 * @throws EE_Error
2768
+	 * @throws InvalidArgumentException
2769
+	 * @throws InvalidDataTypeException
2770
+	 * @throws InvalidInterfaceException
2771
+	 */
2772
+	public function display_about_admin_page()
2773
+	{
2774
+		$this->_display_admin_page(false, true);
2775
+	}
2776
+
2777
+
2778
+	/**
2779
+	 * display_admin_page
2780
+	 * contains the code for actually displaying an admin page
2781
+	 *
2782
+	 * @param boolean $sidebar true with sidebar, false without
2783
+	 * @param boolean $about   use the about admin wrapper instead of the default.
2784
+	 * @return void
2785
+	 * @throws DomainException
2786
+	 * @throws EE_Error
2787
+	 * @throws InvalidArgumentException
2788
+	 * @throws InvalidDataTypeException
2789
+	 * @throws InvalidInterfaceException
2790
+	 */
2791
+	private function _display_admin_page($sidebar = false, $about = false)
2792
+	{
2793
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2794
+		// custom remove metaboxes hook to add or remove any metaboxes to/from Admin pages.
2795
+		do_action('AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes');
2796
+		// set current wp page slug - looks like: event-espresso_page_event_categories
2797
+		// keep in mind "event-espresso" COULD be something else if the top level menu label has been translated.
2798
+		$this->_template_args['current_page'] = $this->_wp_page_slug;
2799
+		$this->_template_args['admin_page_wrapper_div_id'] = $this->_cpt_route
2800
+			? 'poststuff'
2801
+			: 'espresso-default-admin';
2802
+		$template_path = $sidebar
2803
+			? EE_ADMIN_TEMPLATE . 'admin_details_wrapper.template.php'
2804
+			: EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar.template.php';
2805
+		if (defined('DOING_AJAX') && DOING_AJAX) {
2806
+			$template_path = EE_ADMIN_TEMPLATE . 'admin_details_wrapper_no_sidebar_ajax.template.php';
2807
+		}
2808
+		$template_path = ! empty($this->_column_template_path)
2809
+			? $this->_column_template_path : $template_path;
2810
+		$this->_template_args['post_body_content'] = isset($this->_template_args['admin_page_content'])
2811
+			? $this->_template_args['admin_page_content']
2812
+			: '';
2813
+		$this->_template_args['before_admin_page_content'] = isset($this->_template_args['before_admin_page_content'])
2814
+			? $this->_template_args['before_admin_page_content']
2815
+			: '';
2816
+		$this->_template_args['after_admin_page_content'] = isset($this->_template_args['after_admin_page_content'])
2817
+			? $this->_template_args['after_admin_page_content']
2818
+			: '';
2819
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2820
+			$template_path,
2821
+			$this->_template_args,
2822
+			true
2823
+		);
2824
+		// the final template wrapper
2825
+		$this->admin_page_wrapper($about);
2826
+	}
2827
+
2828
+
2829
+	/**
2830
+	 * This is used to display caf preview pages.
2831
+	 *
2832
+	 * @since 4.3.2
2833
+	 * @param string $utm_campaign_source what is the key used for google analytics link
2834
+	 * @param bool   $display_sidebar     whether to use the sidebar template or the full template for the page.  TRUE
2835
+	 *                                    = SHOW sidebar, FALSE = no sidebar. Default no sidebar.
2836
+	 * @return void
2837
+	 * @throws DomainException
2838
+	 * @throws EE_Error
2839
+	 * @throws InvalidArgumentException
2840
+	 * @throws InvalidDataTypeException
2841
+	 * @throws InvalidInterfaceException
2842
+	 */
2843
+	public function display_admin_caf_preview_page($utm_campaign_source = '', $display_sidebar = true)
2844
+	{
2845
+		// let's generate a default preview action button if there isn't one already present.
2846
+		$this->_labels['buttons']['buy_now'] = esc_html__(
2847
+			'Upgrade to Event Espresso 4 Right Now',
2848
+			'event_espresso'
2849
+		);
2850
+		$buy_now_url = add_query_arg(
2851
+			array(
2852
+				'ee_ver'       => 'ee4',
2853
+				'utm_source'   => 'ee4_plugin_admin',
2854
+				'utm_medium'   => 'link',
2855
+				'utm_campaign' => $utm_campaign_source,
2856
+				'utm_content'  => 'buy_now_button',
2857
+			),
2858
+			'http://eventespresso.com/pricing/'
2859
+		);
2860
+		$this->_template_args['preview_action_button'] = ! isset($this->_template_args['preview_action_button'])
2861
+			? $this->get_action_link_or_button(
2862
+				'',
2863
+				'buy_now',
2864
+				array(),
2865
+				'button-primary button-large',
2866
+				$buy_now_url,
2867
+				true
2868
+			)
2869
+			: $this->_template_args['preview_action_button'];
2870
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2871
+			EE_ADMIN_TEMPLATE . 'admin_caf_full_page_preview.template.php',
2872
+			$this->_template_args,
2873
+			true
2874
+		);
2875
+		$this->_display_admin_page($display_sidebar);
2876
+	}
2877
+
2878
+
2879
+	/**
2880
+	 * display_admin_list_table_page_with_sidebar
2881
+	 * generates HTML wrapper for an admin_page with list_table
2882
+	 *
2883
+	 * @return void
2884
+	 * @throws DomainException
2885
+	 * @throws EE_Error
2886
+	 * @throws InvalidArgumentException
2887
+	 * @throws InvalidDataTypeException
2888
+	 * @throws InvalidInterfaceException
2889
+	 */
2890
+	public function display_admin_list_table_page_with_sidebar()
2891
+	{
2892
+		$this->_display_admin_list_table_page(true);
2893
+	}
2894
+
2895
+
2896
+	/**
2897
+	 * display_admin_list_table_page_with_no_sidebar
2898
+	 * generates HTML wrapper for an admin_page with list_table (but with no sidebar)
2899
+	 *
2900
+	 * @return void
2901
+	 * @throws DomainException
2902
+	 * @throws EE_Error
2903
+	 * @throws InvalidArgumentException
2904
+	 * @throws InvalidDataTypeException
2905
+	 * @throws InvalidInterfaceException
2906
+	 */
2907
+	public function display_admin_list_table_page_with_no_sidebar()
2908
+	{
2909
+		$this->_display_admin_list_table_page();
2910
+	}
2911
+
2912
+
2913
+	/**
2914
+	 * generates html wrapper for an admin_list_table page
2915
+	 *
2916
+	 * @param boolean $sidebar whether to display with sidebar or not.
2917
+	 * @return void
2918
+	 * @throws DomainException
2919
+	 * @throws EE_Error
2920
+	 * @throws InvalidArgumentException
2921
+	 * @throws InvalidDataTypeException
2922
+	 * @throws InvalidInterfaceException
2923
+	 */
2924
+	private function _display_admin_list_table_page($sidebar = false)
2925
+	{
2926
+		// setup search attributes
2927
+		$this->_set_search_attributes();
2928
+		$this->_template_args['current_page'] = $this->_wp_page_slug;
2929
+		$template_path = EE_ADMIN_TEMPLATE . 'admin_list_wrapper.template.php';
2930
+		$this->_template_args['table_url'] = defined('DOING_AJAX')
2931
+			? add_query_arg(array('noheader' => 'true', 'route' => $this->_req_action), $this->_admin_base_url)
2932
+			: add_query_arg(array('route' => $this->_req_action), $this->_admin_base_url);
2933
+		$this->_template_args['list_table'] = $this->_list_table_object;
2934
+		$this->_template_args['current_route'] = $this->_req_action;
2935
+		$this->_template_args['list_table_class'] = get_class($this->_list_table_object);
2936
+		$ajax_sorting_callback = $this->_list_table_object->get_ajax_sorting_callback();
2937
+		if (! empty($ajax_sorting_callback)) {
2938
+			$sortable_list_table_form_fields = wp_nonce_field(
2939
+				$ajax_sorting_callback . '_nonce',
2940
+				$ajax_sorting_callback . '_nonce',
2941
+				false,
2942
+				false
2943
+			);
2944
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_page" name="ajax_table_sort_page" value="'
2945
+												. $this->page_slug
2946
+												. '" />';
2947
+			$sortable_list_table_form_fields .= '<input type="hidden" id="ajax_table_sort_action" name="ajax_table_sort_action" value="'
2948
+												. $ajax_sorting_callback
2949
+												. '" />';
2950
+		} else {
2951
+			$sortable_list_table_form_fields = '';
2952
+		}
2953
+		$this->_template_args['sortable_list_table_form_fields'] = $sortable_list_table_form_fields;
2954
+		$hidden_form_fields = isset($this->_template_args['list_table_hidden_fields'])
2955
+			? $this->_template_args['list_table_hidden_fields']
2956
+			: '';
2957
+		$nonce_ref = $this->_req_action . '_nonce';
2958
+		$hidden_form_fields .= '<input type="hidden" name="'
2959
+							   . $nonce_ref
2960
+							   . '" value="'
2961
+							   . wp_create_nonce($nonce_ref)
2962
+							   . '">';
2963
+		$this->_template_args['list_table_hidden_fields'] = $hidden_form_fields;
2964
+		// display message about search results?
2965
+		$this->_template_args['before_list_table'] .= ! empty($this->_req_data['s'])
2966
+			? '<p class="ee-search-results">' . sprintf(
2967
+				esc_html__('Displaying search results for the search string: %1$s', 'event_espresso'),
2968
+				trim($this->_req_data['s'], '%')
2969
+			) . '</p>'
2970
+			: '';
2971
+		// filter before_list_table template arg
2972
+		$this->_template_args['before_list_table'] = apply_filters(
2973
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_arg',
2974
+			$this->_template_args['before_list_table'],
2975
+			$this->page_slug,
2976
+			$this->_req_data,
2977
+			$this->_req_action
2978
+		);
2979
+		// convert to array and filter again
2980
+		// arrays are easier to inject new items in a specific location,
2981
+		// but would not be backwards compatible, so we have to add a new filter
2982
+		$this->_template_args['before_list_table'] = implode(
2983
+			" \n",
2984
+			(array) apply_filters(
2985
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__before_list_table__template_args_array',
2986
+				(array) $this->_template_args['before_list_table'],
2987
+				$this->page_slug,
2988
+				$this->_req_data,
2989
+				$this->_req_action
2990
+			)
2991
+		);
2992
+		// filter after_list_table template arg
2993
+		$this->_template_args['after_list_table'] = apply_filters(
2994
+			'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_arg',
2995
+			$this->_template_args['after_list_table'],
2996
+			$this->page_slug,
2997
+			$this->_req_data,
2998
+			$this->_req_action
2999
+		);
3000
+		// convert to array and filter again
3001
+		// arrays are easier to inject new items in a specific location,
3002
+		// but would not be backwards compatible, so we have to add a new filter
3003
+		$this->_template_args['after_list_table'] = implode(
3004
+			" \n",
3005
+			(array) apply_filters(
3006
+				'FHEE__EE_Admin_Page___display_admin_list_table_page__after_list_table__template_args_array',
3007
+				(array) $this->_template_args['after_list_table'],
3008
+				$this->page_slug,
3009
+				$this->_req_data,
3010
+				$this->_req_action
3011
+			)
3012
+		);
3013
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3014
+			$template_path,
3015
+			$this->_template_args,
3016
+			true
3017
+		);
3018
+		// the final template wrapper
3019
+		if ($sidebar) {
3020
+			$this->display_admin_page_with_sidebar();
3021
+		} else {
3022
+			$this->display_admin_page_with_no_sidebar();
3023
+		}
3024
+	}
3025
+
3026
+
3027
+	/**
3028
+	 * This just prepares a legend using the given items and the admin_details_legend.template.php file and returns the
3029
+	 * html string for the legend.
3030
+	 * $items are expected in an array in the following format:
3031
+	 * $legend_items = array(
3032
+	 *        'item_id' => array(
3033
+	 *            'icon' => 'http://url_to_icon_being_described.png',
3034
+	 *            'desc' => esc_html__('localized description of item');
3035
+	 *        )
3036
+	 * );
3037
+	 *
3038
+	 * @param  array $items see above for format of array
3039
+	 * @return string html string of legend
3040
+	 * @throws DomainException
3041
+	 */
3042
+	protected function _display_legend($items)
3043
+	{
3044
+		$this->_template_args['items'] = apply_filters(
3045
+			'FHEE__EE_Admin_Page___display_legend__items',
3046
+			(array) $items,
3047
+			$this
3048
+		);
3049
+		$this->_template_args['status_change_notice'] = EEH_Template::display_template(
3050
+			EE_ADMIN_TEMPLATE . 'status_change_notice.template.php',
3051
+			[ 'context' => '__admin-legend' ],
3052
+			true
3053
+		);
3054
+		return EEH_Template::display_template(
3055
+			EE_ADMIN_TEMPLATE . 'admin_details_legend.template.php',
3056
+			$this->_template_args,
3057
+			true
3058
+		);
3059
+	}
3060
+
3061
+
3062
+	/**
3063
+	 * This is used whenever we're DOING_AJAX to return a formatted json array that our calling javascript can expect
3064
+	 * The returned json object is created from an array in the following format:
3065
+	 * array(
3066
+	 *  'error' => FALSE, //(default FALSE), contains any errors and/or exceptions (exceptions return json early),
3067
+	 *  'success' => FALSE, //(default FALSE) - contains any special success message.
3068
+	 *  'notices' => '', // - contains any EE_Error formatted notices
3069
+	 *  'content' => 'string can be html', //this is a string of formatted content (can be html)
3070
+	 *  'data' => array() //this can be any key/value pairs that a method returns for later json parsing by the js.
3071
+	 *  We're also going to include the template args with every package (so js can pick out any specific template args
3072
+	 *  that might be included in here)
3073
+	 * )
3074
+	 * The json object is populated by whatever is set in the $_template_args property.
3075
+	 *
3076
+	 * @param bool  $sticky_notices    Used to indicate whether you want to ensure notices are added to a transient
3077
+	 *                                 instead of displayed.
3078
+	 * @param array $notices_arguments Use this to pass any additional args on to the _process_notices.
3079
+	 * @return void
3080
+	 * @throws EE_Error
3081
+	 * @throws InvalidArgumentException
3082
+	 * @throws InvalidDataTypeException
3083
+	 * @throws InvalidInterfaceException
3084
+	 */
3085
+	protected function _return_json($sticky_notices = false, $notices_arguments = array())
3086
+	{
3087
+		// make sure any EE_Error notices have been handled.
3088
+		$this->_process_notices($notices_arguments, true, $sticky_notices);
3089
+		$data = isset($this->_template_args['data']) ? $this->_template_args['data'] : array();
3090
+		unset($this->_template_args['data']);
3091
+		$json = array(
3092
+			'error'     => isset($this->_template_args['error']) ? $this->_template_args['error'] : false,
3093
+			'success'   => isset($this->_template_args['success']) ? $this->_template_args['success'] : false,
3094
+			'errors'    => isset($this->_template_args['errors']) ? $this->_template_args['errors'] : false,
3095
+			'attention' => isset($this->_template_args['attention']) ? $this->_template_args['attention'] : false,
3096
+			'notices'   => EE_Error::get_notices(),
3097
+			'content'   => isset($this->_template_args['admin_page_content'])
3098
+				? $this->_template_args['admin_page_content'] : '',
3099
+			'data'      => array_merge($data, array('template_args' => $this->_template_args)),
3100
+			'isEEajax'  => true
3101
+			// special flag so any ajax.Success methods in js can identify this return package as a EEajax package.
3102
+		);
3103
+		// make sure there are no php errors or headers_sent.  Then we can set correct json header.
3104
+		if (null === error_get_last() || ! headers_sent()) {
3105
+			header('Content-Type: application/json; charset=UTF-8');
3106
+		}
3107
+		echo wp_json_encode($json);
3108
+		exit();
3109
+	}
3110
+
3111
+
3112
+	/**
3113
+	 * Simply a wrapper for the protected method so we can call this outside the class (ONLY when doing ajax)
3114
+	 *
3115
+	 * @return void
3116
+	 * @throws EE_Error
3117
+	 * @throws InvalidArgumentException
3118
+	 * @throws InvalidDataTypeException
3119
+	 * @throws InvalidInterfaceException
3120
+	 */
3121
+	public function return_json()
3122
+	{
3123
+		if (defined('DOING_AJAX') && DOING_AJAX) {
3124
+			$this->_return_json();
3125
+		} else {
3126
+			throw new EE_Error(
3127
+				sprintf(
3128
+					esc_html__('The public %s method can only be called when DOING_AJAX = TRUE', 'event_espresso'),
3129
+					__FUNCTION__
3130
+				)
3131
+			);
3132
+		}
3133
+	}
3134
+
3135
+
3136
+	/**
3137
+	 * This provides a way for child hook classes to send along themselves by reference so methods/properties within
3138
+	 * them can be accessed by EE_Admin_child pages. This is assigned to the $_hook_obj property.
3139
+	 *
3140
+	 * @param EE_Admin_Hooks $hook_obj This will be the object for the EE_Admin_Hooks child
3141
+	 */
3142
+	public function set_hook_object(EE_Admin_Hooks $hook_obj)
3143
+	{
3144
+		$this->_hook_obj = $hook_obj;
3145
+	}
3146
+
3147
+
3148
+	/**
3149
+	 *        generates  HTML wrapper with Tabbed nav for an admin page
3150
+	 *
3151
+	 * @param boolean $about whether to use the special about page wrapper or default.
3152
+	 * @return void
3153
+	 * @throws DomainException
3154
+	 * @throws EE_Error
3155
+	 * @throws InvalidArgumentException
3156
+	 * @throws InvalidDataTypeException
3157
+	 * @throws InvalidInterfaceException
3158
+	 */
3159
+	public function admin_page_wrapper($about = false)
3160
+	{
3161
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3162
+		$this->_nav_tabs = $this->_get_main_nav_tabs();
3163
+		$this->_template_args['nav_tabs'] = $this->_nav_tabs;
3164
+		$this->_template_args['admin_page_title'] = $this->_admin_page_title;
3165
+		$this->_template_args['before_admin_page_content'] = apply_filters(
3166
+			"FHEE_before_admin_page_content{$this->_current_page}{$this->_current_view}",
3167
+			isset($this->_template_args['before_admin_page_content'])
3168
+				? $this->_template_args['before_admin_page_content']
3169
+				: ''
3170
+		);
3171
+		$this->_template_args['after_admin_page_content'] = apply_filters(
3172
+			"FHEE_after_admin_page_content{$this->_current_page}{$this->_current_view}",
3173
+			isset($this->_template_args['after_admin_page_content'])
3174
+				? $this->_template_args['after_admin_page_content']
3175
+				: ''
3176
+		);
3177
+		$this->_template_args['after_admin_page_content'] .= $this->_set_help_popup_content();
3178
+		// load settings page wrapper template
3179
+		$template_path = ! defined('DOING_AJAX')
3180
+			? EE_ADMIN_TEMPLATE . 'admin_wrapper.template.php'
3181
+			: EE_ADMIN_TEMPLATE
3182
+			  . 'admin_wrapper_ajax.template.php';
3183
+		// about page?
3184
+		$template_path = $about
3185
+			? EE_ADMIN_TEMPLATE . 'about_admin_wrapper.template.php'
3186
+			: $template_path;
3187
+		if (defined('DOING_AJAX')) {
3188
+			$this->_template_args['admin_page_content'] = EEH_Template::display_template(
3189
+				$template_path,
3190
+				$this->_template_args,
3191
+				true
3192
+			);
3193
+			$this->_return_json();
3194
+		} else {
3195
+			EEH_Template::display_template($template_path, $this->_template_args);
3196
+		}
3197
+	}
3198
+
3199
+
3200
+	/**
3201
+	 * This returns the admin_nav tabs html using the configuration in the _nav_tabs property
3202
+	 *
3203
+	 * @return string html
3204
+	 * @throws EE_Error
3205
+	 */
3206
+	protected function _get_main_nav_tabs()
3207
+	{
3208
+		// let's generate the html using the EEH_Tabbed_Content helper.
3209
+		// We do this here so that it's possible for child classes to add in nav tabs dynamically at the last minute
3210
+		// (rather than setting in the page_routes array)
3211
+		return EEH_Tabbed_Content::display_admin_nav_tabs($this->_nav_tabs);
3212
+	}
3213
+
3214
+
3215
+	/**
3216
+	 *        sort nav tabs
3217
+	 *
3218
+	 * @param $a
3219
+	 * @param $b
3220
+	 * @return int
3221
+	 */
3222
+	private function _sort_nav_tabs($a, $b)
3223
+	{
3224
+		if ($a['order'] === $b['order']) {
3225
+			return 0;
3226
+		}
3227
+		return ($a['order'] < $b['order']) ? -1 : 1;
3228
+	}
3229
+
3230
+
3231
+	/**
3232
+	 *    generates HTML for the forms used on admin pages
3233
+	 *
3234
+	 * @param    array $input_vars - array of input field details
3235
+	 * @param string   $generator  (options are 'string' or 'array', basically use this to indicate which generator to
3236
+	 *                             use)
3237
+	 * @param bool     $id
3238
+	 * @return string
3239
+	 * @uses   EEH_Form_Fields::get_form_fields (/helper/EEH_Form_Fields.helper.php)
3240
+	 * @uses   EEH_Form_Fields::get_form_fields_array (/helper/EEH_Form_Fields.helper.php)
3241
+	 */
3242
+	protected function _generate_admin_form_fields($input_vars = array(), $generator = 'string', $id = false)
3243
+	{
3244
+		return $generator === 'string'
3245
+			? EEH_Form_Fields::get_form_fields($input_vars, $id)
3246
+			: EEH_Form_Fields::get_form_fields_array($input_vars);
3247
+	}
3248
+
3249
+
3250
+	/**
3251
+	 * generates the "Save" and "Save & Close" buttons for edit forms
3252
+	 *
3253
+	 * @param bool             $both     if true then both buttons will be generated.  If false then just the "Save &
3254
+	 *                                   Close" button.
3255
+	 * @param array            $text     if included, generator will use the given text for the buttons ( array([0] =>
3256
+	 *                                   'Save', [1] => 'save & close')
3257
+	 * @param array            $actions  if included allows us to set the actions that each button will carry out (i.e.
3258
+	 *                                   via the "name" value in the button).  We can also use this to just dump
3259
+	 *                                   default actions by submitting some other value.
3260
+	 * @param bool|string|null $referrer if false then we just do the default action on save and close.  Other wise it
3261
+	 *                                   will use the $referrer string. IF null, then we don't do ANYTHING on save and
3262
+	 *                                   close (normal form handling).
3263
+	 */
3264
+	protected function _set_save_buttons($both = true, $text = array(), $actions = array(), $referrer = null)
3265
+	{
3266
+		// make sure $text and $actions are in an array
3267
+		$text = (array) $text;
3268
+		$actions = (array) $actions;
3269
+		$referrer_url = empty($referrer)
3270
+			? '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3271
+			  . $_SERVER['REQUEST_URI']
3272
+			  . '" />'
3273
+			: '<input type="hidden" id="save_and_close_referrer" name="save_and_close_referrer" value="'
3274
+			  . $referrer
3275
+			  . '" />';
3276
+		$button_text = ! empty($text)
3277
+			? $text
3278
+			: array(
3279
+				esc_html__('Save', 'event_espresso'),
3280
+				esc_html__('Save and Close', 'event_espresso'),
3281
+			);
3282
+		$default_names = array('save', 'save_and_close');
3283
+		// add in a hidden index for the current page (so save and close redirects properly)
3284
+		$this->_template_args['save_buttons'] = $referrer_url;
3285
+		foreach ($button_text as $key => $button) {
3286
+			$ref = $default_names[ $key ];
3287
+			$this->_template_args['save_buttons'] .= '<input type="submit" class="button-primary '
3288
+													 . $ref
3289
+													 . '" value="'
3290
+													 . $button
3291
+													 . '" name="'
3292
+													 . (! empty($actions) ? $actions[ $key ] : $ref)
3293
+													 . '" id="'
3294
+													 . $this->_current_view . '_' . $ref
3295
+													 . '" />';
3296
+			if (! $both) {
3297
+				break;
3298
+			}
3299
+		}
3300
+	}
3301
+
3302
+
3303
+	/**
3304
+	 * Wrapper for the protected function.  Allows plugins/addons to call this to set the form tags.
3305
+	 *
3306
+	 * @see   $this->_set_add_edit_form_tags() for details on params
3307
+	 * @since 4.6.0
3308
+	 * @param string $route
3309
+	 * @param array  $additional_hidden_fields
3310
+	 */
3311
+	public function set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3312
+	{
3313
+		$this->_set_add_edit_form_tags($route, $additional_hidden_fields);
3314
+	}
3315
+
3316
+
3317
+	/**
3318
+	 * set form open and close tags on add/edit pages.
3319
+	 *
3320
+	 * @param string $route                    the route you want the form to direct to
3321
+	 * @param array  $additional_hidden_fields any additional hidden fields required in the form header
3322
+	 * @return void
3323
+	 */
3324
+	protected function _set_add_edit_form_tags($route = '', $additional_hidden_fields = array())
3325
+	{
3326
+		if (empty($route)) {
3327
+			$user_msg = esc_html__(
3328
+				'An error occurred. No action was set for this page\'s form.',
3329
+				'event_espresso'
3330
+			);
3331
+			$dev_msg = $user_msg . "\n"
3332
+					   . sprintf(
3333
+						   esc_html__('The $route argument is required for the %s->%s method.', 'event_espresso'),
3334
+						   __FUNCTION__,
3335
+						   EE_Admin_Page::class
3336
+					   );
3337
+			EE_Error::add_error($user_msg . '||' . $dev_msg, __FILE__, __FUNCTION__, __LINE__);
3338
+		}
3339
+		// open form
3340
+		$this->_template_args['before_admin_page_content'] = '<form name="form" method="post" action="'
3341
+															 . $this->_admin_base_url
3342
+															 . '" id="'
3343
+															 . $route
3344
+															 . '_event_form" >';
3345
+		// add nonce
3346
+		$nonce = wp_nonce_field($route . '_nonce', $route . '_nonce', false, false);
3347
+		$this->_template_args['before_admin_page_content'] .= "\n\t" . $nonce;
3348
+		// add REQUIRED form action
3349
+		$hidden_fields = array(
3350
+			'action' => array('type' => 'hidden', 'value' => $route),
3351
+		);
3352
+		// merge arrays
3353
+		$hidden_fields = is_array($additional_hidden_fields)
3354
+			? array_merge($hidden_fields, $additional_hidden_fields)
3355
+			: $hidden_fields;
3356
+		// generate form fields
3357
+		$form_fields = $this->_generate_admin_form_fields($hidden_fields, 'array');
3358
+		// add fields to form
3359
+		foreach ((array) $form_fields as $field_name => $form_field) {
3360
+			$this->_template_args['before_admin_page_content'] .= "\n\t" . $form_field['field'];
3361
+		}
3362
+		// close form
3363
+		$this->_template_args['after_admin_page_content'] = '</form>';
3364
+	}
3365
+
3366
+
3367
+	/**
3368
+	 * Public Wrapper for _redirect_after_action() method since its
3369
+	 * discovered it would be useful for external code to have access.
3370
+	 *
3371
+	 * @param bool   $success
3372
+	 * @param string $what
3373
+	 * @param string $action_desc
3374
+	 * @param array  $query_args
3375
+	 * @param bool   $override_overwrite
3376
+	 * @throws EE_Error
3377
+	 * @throws InvalidArgumentException
3378
+	 * @throws InvalidDataTypeException
3379
+	 * @throws InvalidInterfaceException
3380
+	 * @see   EE_Admin_Page::_redirect_after_action() for params.
3381
+	 * @since 4.5.0
3382
+	 */
3383
+	public function redirect_after_action(
3384
+		$success = false,
3385
+		$what = 'item',
3386
+		$action_desc = 'processed',
3387
+		$query_args = array(),
3388
+		$override_overwrite = false
3389
+	) {
3390
+		$this->_redirect_after_action(
3391
+			$success,
3392
+			$what,
3393
+			$action_desc,
3394
+			$query_args,
3395
+			$override_overwrite
3396
+		);
3397
+	}
3398
+
3399
+
3400
+	/**
3401
+	 * Helper method for merging existing request data with the returned redirect url.
3402
+	 *
3403
+	 * This is typically used for redirects after an action so that if the original view was a filtered view those
3404
+	 * filters are still applied.
3405
+	 *
3406
+	 * @param array $new_route_data
3407
+	 * @return array
3408
+	 */
3409
+	protected function mergeExistingRequestParamsWithRedirectArgs(array $new_route_data)
3410
+	{
3411
+		foreach ($this->_req_data as $ref => $value) {
3412
+			// unset nonces
3413
+			if (strpos($ref, 'nonce') !== false) {
3414
+				unset($this->_req_data[ $ref ]);
3415
+				continue;
3416
+			}
3417
+			// urlencode values.
3418
+			$value = is_array($value) ? array_map('urlencode', $value) : urlencode($value);
3419
+			$this->_req_data[ $ref ] = $value;
3420
+		}
3421
+		return array_merge($this->_req_data, $new_route_data);
3422
+	}
3423
+
3424
+
3425
+	/**
3426
+	 *    _redirect_after_action
3427
+	 *
3428
+	 * @param int    $success            - whether success was for two or more records, or just one, or none
3429
+	 * @param string $what               - what the action was performed on
3430
+	 * @param string $action_desc        - what was done ie: updated, deleted, etc
3431
+	 * @param array  $query_args         - an array of query_args to be added to the URL to redirect to after the admin
3432
+	 *                                   action is completed
3433
+	 * @param BOOL   $override_overwrite by default all EE_Error::success messages are overwritten, this allows you to
3434
+	 *                                   override this so that they show.
3435
+	 * @return void
3436
+	 * @throws EE_Error
3437
+	 * @throws InvalidArgumentException
3438
+	 * @throws InvalidDataTypeException
3439
+	 * @throws InvalidInterfaceException
3440
+	 */
3441
+	protected function _redirect_after_action(
3442
+		$success = 0,
3443
+		$what = 'item',
3444
+		$action_desc = 'processed',
3445
+		$query_args = array(),
3446
+		$override_overwrite = false
3447
+	) {
3448
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
3449
+		// class name for actions/filters.
3450
+		$classname = get_class($this);
3451
+		// set redirect url.
3452
+		// Note if there is a "page" index in the $query_args then we go with vanilla admin.php route,
3453
+		// otherwise we go with whatever is set as the _admin_base_url
3454
+		$redirect_url = isset($query_args['page']) ? admin_url('admin.php') : $this->_admin_base_url;
3455
+		$notices = EE_Error::get_notices(false);
3456
+		// overwrite default success messages //BUT ONLY if overwrite not overridden
3457
+		if (! $override_overwrite || ! empty($notices['errors'])) {
3458
+			EE_Error::overwrite_success();
3459
+		}
3460
+		if (! empty($what) && ! empty($action_desc) && empty($notices['errors'])) {
3461
+			// how many records affected ? more than one record ? or just one ?
3462
+			if ($success > 1) {
3463
+				// set plural msg
3464
+				EE_Error::add_success(
3465
+					sprintf(
3466
+						esc_html__('The "%s" have been successfully %s.', 'event_espresso'),
3467
+						$what,
3468
+						$action_desc
3469
+					),
3470
+					__FILE__,
3471
+					__FUNCTION__,
3472
+					__LINE__
3473
+				);
3474
+			} elseif ($success === 1) {
3475
+				// set singular msg
3476
+				EE_Error::add_success(
3477
+					sprintf(
3478
+						esc_html__('The "%s" has been successfully %s.', 'event_espresso'),
3479
+						$what,
3480
+						$action_desc
3481
+					),
3482
+					__FILE__,
3483
+					__FUNCTION__,
3484
+					__LINE__
3485
+				);
3486
+			}
3487
+		}
3488
+		// check that $query_args isn't something crazy
3489
+		if (! is_array($query_args)) {
3490
+			$query_args = array();
3491
+		}
3492
+		/**
3493
+		 * Allow injecting actions before the query_args are modified for possible different
3494
+		 * redirections on save and close actions
3495
+		 *
3496
+		 * @since 4.2.0
3497
+		 * @param array $query_args       The original query_args array coming into the
3498
+		 *                                method.
3499
+		 */
3500
+		do_action(
3501
+			"AHEE__{$classname}___redirect_after_action__before_redirect_modification_{$this->_req_action}",
3502
+			$query_args
3503
+		);
3504
+		// calculate where we're going (if we have a "save and close" button pushed)
3505
+		if (isset($this->_req_data['save_and_close'], $this->_req_data['save_and_close_referrer'])) {
3506
+			// even though we have the save_and_close referrer, we need to parse the url for the action in order to generate a nonce
3507
+			$parsed_url = parse_url($this->_req_data['save_and_close_referrer']);
3508
+			// regenerate query args array from referrer URL
3509
+			parse_str($parsed_url['query'], $query_args);
3510
+			// correct page and action will be in the query args now
3511
+			$redirect_url = admin_url('admin.php');
3512
+		}
3513
+		// merge any default query_args set in _default_route_query_args property
3514
+		if (! empty($this->_default_route_query_args) && ! $this->_is_UI_request) {
3515
+			$args_to_merge = array();
3516
+			foreach ($this->_default_route_query_args as $query_param => $query_value) {
3517
+				// is there a wp_referer array in our _default_route_query_args property?
3518
+				if ($query_param === 'wp_referer') {
3519
+					$query_value = (array) $query_value;
3520
+					foreach ($query_value as $reference => $value) {
3521
+						if (strpos($reference, 'nonce') !== false) {
3522
+							continue;
3523
+						}
3524
+						// finally we will override any arguments in the referer with
3525
+						// what might be set on the _default_route_query_args array.
3526
+						if (isset($this->_default_route_query_args[ $reference ])) {
3527
+							$args_to_merge[ $reference ] = urlencode($this->_default_route_query_args[ $reference ]);
3528
+						} else {
3529
+							$args_to_merge[ $reference ] = urlencode($value);
3530
+						}
3531
+					}
3532
+					continue;
3533
+				}
3534
+				$args_to_merge[ $query_param ] = $query_value;
3535
+			}
3536
+			// now let's merge these arguments but override with what was specifically sent in to the
3537
+			// redirect.
3538
+			$query_args = array_merge($args_to_merge, $query_args);
3539
+		}
3540
+		$this->_process_notices($query_args);
3541
+		// generate redirect url
3542
+		// if redirecting to anything other than the main page, add a nonce
3543
+		if (isset($query_args['action'])) {
3544
+			// manually generate wp_nonce and merge that with the query vars
3545
+			// becuz the wp_nonce_url function wrecks havoc on some vars
3546
+			$query_args['_wpnonce'] = wp_create_nonce($query_args['action'] . '_nonce');
3547
+		}
3548
+		// we're adding some hooks and filters in here for processing any things just before redirects
3549
+		// (example: an admin page has done an insert or update and we want to run something after that).
3550
+		do_action('AHEE_redirect_' . $classname . $this->_req_action, $query_args);
3551
+		$redirect_url = apply_filters(
3552
+			'FHEE_redirect_' . $classname . $this->_req_action,
3553
+			EE_Admin_Page::add_query_args_and_nonce($query_args, $redirect_url),
3554
+			$query_args
3555
+		);
3556
+		// check if we're doing ajax.  If we are then lets just return the results and js can handle how it wants.
3557
+		if (defined('DOING_AJAX')) {
3558
+			$default_data = array(
3559
+				'close'        => true,
3560
+				'redirect_url' => $redirect_url,
3561
+				'where'        => 'main',
3562
+				'what'         => 'append',
3563
+			);
3564
+			$this->_template_args['success'] = $success;
3565
+			$this->_template_args['data'] = ! empty($this->_template_args['data']) ? array_merge(
3566
+				$default_data,
3567
+				$this->_template_args['data']
3568
+			) : $default_data;
3569
+			$this->_return_json();
3570
+		}
3571
+		wp_safe_redirect($redirect_url);
3572
+		exit();
3573
+	}
3574
+
3575
+
3576
+	/**
3577
+	 * process any notices before redirecting (or returning ajax request)
3578
+	 * This method sets the $this->_template_args['notices'] attribute;
3579
+	 *
3580
+	 * @param array $query_args         any query args that need to be used for notice transient ('action')
3581
+	 * @param bool  $skip_route_verify  This is typically used when we are processing notices REALLY early and
3582
+	 *                                  page_routes haven't been defined yet.
3583
+	 * @param bool  $sticky_notices     This is used to flag that regardless of whether this is doing_ajax or not, we
3584
+	 *                                  still save a transient for the notice.
3585
+	 * @return void
3586
+	 * @throws EE_Error
3587
+	 * @throws InvalidArgumentException
3588
+	 * @throws InvalidDataTypeException
3589
+	 * @throws InvalidInterfaceException
3590
+	 */
3591
+	protected function _process_notices($query_args = array(), $skip_route_verify = false, $sticky_notices = true)
3592
+	{
3593
+		// first let's set individual error properties if doing_ajax and the properties aren't already set.
3594
+		if (defined('DOING_AJAX') && DOING_AJAX) {
3595
+			$notices = EE_Error::get_notices(false);
3596
+			if (empty($this->_template_args['success'])) {
3597
+				$this->_template_args['success'] = isset($notices['success']) ? $notices['success'] : false;
3598
+			}
3599
+			if (empty($this->_template_args['errors'])) {
3600
+				$this->_template_args['errors'] = isset($notices['errors']) ? $notices['errors'] : false;
3601
+			}
3602
+			if (empty($this->_template_args['attention'])) {
3603
+				$this->_template_args['attention'] = isset($notices['attention']) ? $notices['attention'] : false;
3604
+			}
3605
+		}
3606
+		$this->_template_args['notices'] = EE_Error::get_notices();
3607
+		// IF this isn't ajax we need to create a transient for the notices using the route (however, overridden if $sticky_notices == true)
3608
+		if (! defined('DOING_AJAX') || $sticky_notices) {
3609
+			$route = isset($query_args['action']) ? $query_args['action'] : 'default';
3610
+			$this->_add_transient(
3611
+				$route,
3612
+				$this->_template_args['notices'],
3613
+				true,
3614
+				$skip_route_verify
3615
+			);
3616
+		}
3617
+	}
3618
+
3619
+
3620
+	/**
3621
+	 * get_action_link_or_button
3622
+	 * returns the button html for adding, editing, or deleting an item (depending on given type)
3623
+	 *
3624
+	 * @param string $action        use this to indicate which action the url is generated with.
3625
+	 * @param string $type          accepted strings must be defined in the $_labels['button'] array(as the key)
3626
+	 *                              property.
3627
+	 * @param array  $extra_request if the button requires extra params you can include them in $key=>$value pairs.
3628
+	 * @param string $class         Use this to give the class for the button. Defaults to 'button-primary'
3629
+	 * @param string $base_url      If this is not provided
3630
+	 *                              the _admin_base_url will be used as the default for the button base_url.
3631
+	 *                              Otherwise this value will be used.
3632
+	 * @param bool   $exclude_nonce If true then no nonce will be in the generated button link.
3633
+	 * @return string
3634
+	 * @throws InvalidArgumentException
3635
+	 * @throws InvalidInterfaceException
3636
+	 * @throws InvalidDataTypeException
3637
+	 * @throws EE_Error
3638
+	 */
3639
+	public function get_action_link_or_button(
3640
+		$action,
3641
+		$type = 'add',
3642
+		$extra_request = array(),
3643
+		$class = 'button-primary',
3644
+		$base_url = '',
3645
+		$exclude_nonce = false
3646
+	) {
3647
+		// first let's validate the action (if $base_url is FALSE otherwise validation will happen further along)
3648
+		if (empty($base_url) && ! isset($this->_page_routes[ $action ])) {
3649
+			throw new EE_Error(
3650
+				sprintf(
3651
+					esc_html__(
3652
+						'There is no page route for given action for the button.  This action was given: %s',
3653
+						'event_espresso'
3654
+					),
3655
+					$action
3656
+				)
3657
+			);
3658
+		}
3659
+		if (! isset($this->_labels['buttons'][ $type ])) {
3660
+			throw new EE_Error(
3661
+				sprintf(
3662
+					__(
3663
+						'There is no label for the given button type (%s). Labels are set in the <code>_page_config</code> property.',
3664
+						'event_espresso'
3665
+					),
3666
+					$type
3667
+				)
3668
+			);
3669
+		}
3670
+		// finally check user access for this button.
3671
+		$has_access = $this->check_user_access($action, true);
3672
+		if (! $has_access) {
3673
+			return '';
3674
+		}
3675
+		$_base_url = ! $base_url ? $this->_admin_base_url : $base_url;
3676
+		$query_args = array(
3677
+			'action' => $action,
3678
+		);
3679
+		// merge extra_request args but make sure our original action takes precedence and doesn't get overwritten.
3680
+		if (! empty($extra_request)) {
3681
+			$query_args = array_merge($extra_request, $query_args);
3682
+		}
3683
+		$url = EE_Admin_Page::add_query_args_and_nonce($query_args, $_base_url, false, $exclude_nonce);
3684
+		return EEH_Template::get_button_or_link($url, $this->_labels['buttons'][ $type ], $class);
3685
+	}
3686
+
3687
+
3688
+	/**
3689
+	 * _per_page_screen_option
3690
+	 * Utility function for adding in a per_page_option in the screen_options_dropdown.
3691
+	 *
3692
+	 * @return void
3693
+	 * @throws InvalidArgumentException
3694
+	 * @throws InvalidInterfaceException
3695
+	 * @throws InvalidDataTypeException
3696
+	 */
3697
+	protected function _per_page_screen_option()
3698
+	{
3699
+		$option = 'per_page';
3700
+		$args = array(
3701
+			'label'   => apply_filters(
3702
+				'FHEE__EE_Admin_Page___per_page_screen_options___label',
3703
+				$this->_admin_page_title,
3704
+				$this
3705
+			),
3706
+			'default' => (int) apply_filters(
3707
+				'FHEE__EE_Admin_Page___per_page_screen_options__default',
3708
+				20
3709
+			),
3710
+			'option'  => $this->_current_page . '_' . $this->_current_view . '_per_page',
3711
+		);
3712
+		// ONLY add the screen option if the user has access to it.
3713
+		if ($this->check_user_access($this->_current_view, true)) {
3714
+			add_screen_option($option, $args);
3715
+		}
3716
+	}
3717
+
3718
+
3719
+	/**
3720
+	 * set_per_page_screen_option
3721
+	 * All this does is make sure that WordPress saves any per_page screen options (if set) for the current page.
3722
+	 * we have to do this rather than running inside the 'set-screen-options' hook because it runs earlier than
3723
+	 * admin_menu.
3724
+	 *
3725
+	 * @return void
3726
+	 */
3727
+	private function _set_per_page_screen_options()
3728
+	{
3729
+		if (isset($_POST['wp_screen_options']) && is_array($_POST['wp_screen_options'])) {
3730
+			check_admin_referer('screen-options-nonce', 'screenoptionnonce');
3731
+			if (! $user = wp_get_current_user()) {
3732
+				return;
3733
+			}
3734
+			$option = $_POST['wp_screen_options']['option'];
3735
+			$value = $_POST['wp_screen_options']['value'];
3736
+			if ($option !== sanitize_key($option)) {
3737
+				return;
3738
+			}
3739
+			$map_option = $option;
3740
+			$option = str_replace('-', '_', $option);
3741
+			switch ($map_option) {
3742
+				case $this->_current_page . '_' . $this->_current_view . '_per_page':
3743
+					$value = (int) $value;
3744
+					$max_value = apply_filters(
3745
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__max_value',
3746
+						999,
3747
+						$this->_current_page,
3748
+						$this->_current_view
3749
+					);
3750
+					if ($value < 1) {
3751
+						return;
3752
+					}
3753
+					$value = min($value, $max_value);
3754
+					break;
3755
+				default:
3756
+					$value = apply_filters(
3757
+						'FHEE__EE_Admin_Page___set_per_page_screen_options__value',
3758
+						false,
3759
+						$option,
3760
+						$value
3761
+					);
3762
+					if (false === $value) {
3763
+						return;
3764
+					}
3765
+					break;
3766
+			}
3767
+			update_user_meta($user->ID, $option, $value);
3768
+			wp_safe_redirect(remove_query_arg(array('pagenum', 'apage', 'paged'), wp_get_referer()));
3769
+			exit;
3770
+		}
3771
+	}
3772
+
3773
+
3774
+	/**
3775
+	 * This just allows for setting the $_template_args property if it needs to be set outside the object
3776
+	 *
3777
+	 * @param array $data array that will be assigned to template args.
3778
+	 */
3779
+	public function set_template_args($data)
3780
+	{
3781
+		$this->_template_args = array_merge($this->_template_args, (array) $data);
3782
+	}
3783
+
3784
+
3785
+	/**
3786
+	 * This makes available the WP transient system for temporarily moving data between routes
3787
+	 *
3788
+	 * @param string $route             the route that should receive the transient
3789
+	 * @param array  $data              the data that gets sent
3790
+	 * @param bool   $notices           If this is for notices then we use this to indicate so, otherwise its just a
3791
+	 *                                  normal route transient.
3792
+	 * @param bool   $skip_route_verify Used to indicate we want to skip route verification.  This is usually ONLY used
3793
+	 *                                  when we are adding a transient before page_routes have been defined.
3794
+	 * @return void
3795
+	 * @throws EE_Error
3796
+	 */
3797
+	protected function _add_transient($route, $data, $notices = false, $skip_route_verify = false)
3798
+	{
3799
+		$user_id = get_current_user_id();
3800
+		if (! $skip_route_verify) {
3801
+			$this->_verify_route($route);
3802
+		}
3803
+		// now let's set the string for what kind of transient we're setting
3804
+		$transient = $notices
3805
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3806
+			: 'rte_tx_' . $route . '_' . $user_id;
3807
+		$data = $notices ? array('notices' => $data) : $data;
3808
+		// is there already a transient for this route?  If there is then let's ADD to that transient
3809
+		$existing = is_multisite() && is_network_admin()
3810
+			? get_site_transient($transient)
3811
+			: get_transient($transient);
3812
+		if ($existing) {
3813
+			$data = array_merge((array) $data, (array) $existing);
3814
+		}
3815
+		if (is_multisite() && is_network_admin()) {
3816
+			set_site_transient($transient, $data, 8);
3817
+		} else {
3818
+			set_transient($transient, $data, 8);
3819
+		}
3820
+	}
3821
+
3822
+
3823
+	/**
3824
+	 * this retrieves the temporary transient that has been set for moving data between routes.
3825
+	 *
3826
+	 * @param bool   $notices true we get notices transient. False we just return normal route transient
3827
+	 * @param string $route
3828
+	 * @return mixed data
3829
+	 */
3830
+	protected function _get_transient($notices = false, $route = '')
3831
+	{
3832
+		$user_id = get_current_user_id();
3833
+		$route = ! $route ? $this->_req_action : $route;
3834
+		$transient = $notices
3835
+			? 'ee_rte_n_tx_' . $route . '_' . $user_id
3836
+			: 'rte_tx_' . $route . '_' . $user_id;
3837
+		$data = is_multisite() && is_network_admin()
3838
+			? get_site_transient($transient)
3839
+			: get_transient($transient);
3840
+		// delete transient after retrieval (just in case it hasn't expired);
3841
+		if (is_multisite() && is_network_admin()) {
3842
+			delete_site_transient($transient);
3843
+		} else {
3844
+			delete_transient($transient);
3845
+		}
3846
+		return $notices && isset($data['notices']) ? $data['notices'] : $data;
3847
+	}
3848
+
3849
+
3850
+	/**
3851
+	 * The purpose of this method is just to run garbage collection on any EE transients that might have expired but
3852
+	 * would not be called later. This will be assigned to run on a specific EE Admin page. (place the method in the
3853
+	 * default route callback on the EE_Admin page you want it run.)
3854
+	 *
3855
+	 * @return void
3856
+	 */
3857
+	protected function _transient_garbage_collection()
3858
+	{
3859
+		global $wpdb;
3860
+		// retrieve all existing transients
3861
+		$query = "SELECT option_name FROM {$wpdb->options} WHERE option_name LIKE '%rte_tx_%' OR option_name LIKE '%rte_n_tx_%'";
3862
+		if ($results = $wpdb->get_results($query)) {
3863
+			foreach ($results as $result) {
3864
+				$transient = str_replace('_transient_', '', $result->option_name);
3865
+				get_transient($transient);
3866
+				if (is_multisite() && is_network_admin()) {
3867
+					get_site_transient($transient);
3868
+				}
3869
+			}
3870
+		}
3871
+	}
3872
+
3873
+
3874
+	/**
3875
+	 * get_view
3876
+	 *
3877
+	 * @return string content of _view property
3878
+	 */
3879
+	public function get_view()
3880
+	{
3881
+		return $this->_view;
3882
+	}
3883
+
3884
+
3885
+	/**
3886
+	 * getter for the protected $_views property
3887
+	 *
3888
+	 * @return array
3889
+	 */
3890
+	public function get_views()
3891
+	{
3892
+		return $this->_views;
3893
+	}
3894
+
3895
+
3896
+	/**
3897
+	 * get_current_page
3898
+	 *
3899
+	 * @return string _current_page property value
3900
+	 */
3901
+	public function get_current_page()
3902
+	{
3903
+		return $this->_current_page;
3904
+	}
3905
+
3906
+
3907
+	/**
3908
+	 * get_current_view
3909
+	 *
3910
+	 * @return string _current_view property value
3911
+	 */
3912
+	public function get_current_view()
3913
+	{
3914
+		return $this->_current_view;
3915
+	}
3916
+
3917
+
3918
+	/**
3919
+	 * get_current_screen
3920
+	 *
3921
+	 * @return object The current WP_Screen object
3922
+	 */
3923
+	public function get_current_screen()
3924
+	{
3925
+		return $this->_current_screen;
3926
+	}
3927
+
3928
+
3929
+	/**
3930
+	 * get_current_page_view_url
3931
+	 *
3932
+	 * @return string This returns the url for the current_page_view.
3933
+	 */
3934
+	public function get_current_page_view_url()
3935
+	{
3936
+		return $this->_current_page_view_url;
3937
+	}
3938
+
3939
+
3940
+	/**
3941
+	 * just returns the _req_data property
3942
+	 *
3943
+	 * @return array
3944
+	 */
3945
+	public function get_request_data()
3946
+	{
3947
+		return $this->_req_data;
3948
+	}
3949
+
3950
+
3951
+	/**
3952
+	 * returns the _req_data protected property
3953
+	 *
3954
+	 * @return string
3955
+	 */
3956
+	public function get_req_action()
3957
+	{
3958
+		return $this->_req_action;
3959
+	}
3960
+
3961
+
3962
+	/**
3963
+	 * @return bool  value of $_is_caf property
3964
+	 */
3965
+	public function is_caf()
3966
+	{
3967
+		return $this->_is_caf;
3968
+	}
3969
+
3970
+
3971
+	/**
3972
+	 * @return mixed
3973
+	 */
3974
+	public function default_espresso_metaboxes()
3975
+	{
3976
+		return $this->_default_espresso_metaboxes;
3977
+	}
3978
+
3979
+
3980
+	/**
3981
+	 * @return mixed
3982
+	 */
3983
+	public function admin_base_url()
3984
+	{
3985
+		return $this->_admin_base_url;
3986
+	}
3987
+
3988
+
3989
+	/**
3990
+	 * @return mixed
3991
+	 */
3992
+	public function wp_page_slug()
3993
+	{
3994
+		return $this->_wp_page_slug;
3995
+	}
3996
+
3997
+
3998
+	/**
3999
+	 * updates  espresso configuration settings
4000
+	 *
4001
+	 * @param string                   $tab
4002
+	 * @param EE_Config_Base|EE_Config $config
4003
+	 * @param string                   $file file where error occurred
4004
+	 * @param string                   $func function  where error occurred
4005
+	 * @param string                   $line line no where error occurred
4006
+	 * @return boolean
4007
+	 */
4008
+	protected function _update_espresso_configuration($tab, $config, $file = '', $func = '', $line = '')
4009
+	{
4010
+		// remove any options that are NOT going to be saved with the config settings.
4011
+		if (isset($config->core->ee_ueip_optin)) {
4012
+			// TODO: remove the following two lines and make sure values are migrated from 3.1
4013
+			update_option('ee_ueip_optin', $config->core->ee_ueip_optin);
4014
+			update_option('ee_ueip_has_notified', true);
4015
+		}
4016
+		// and save it (note we're also doing the network save here)
4017
+		$net_saved = is_main_site() ? EE_Network_Config::instance()->update_config(false, false) : true;
4018
+		$config_saved = EE_Config::instance()->update_espresso_config(false, false);
4019
+		if ($config_saved && $net_saved) {
4020
+			EE_Error::add_success(sprintf(__('"%s" have been successfully updated.', 'event_espresso'), $tab));
4021
+			return true;
4022
+		}
4023
+		EE_Error::add_error(sprintf(__('The "%s" were not updated.', 'event_espresso'), $tab), $file, $func, $line);
4024
+		return false;
4025
+	}
4026
+
4027
+
4028
+	/**
4029
+	 * Returns an array to be used for EE_FOrm_Fields.helper.php's select_input as the $values argument.
4030
+	 *
4031
+	 * @return array
4032
+	 */
4033
+	public function get_yes_no_values()
4034
+	{
4035
+		return $this->_yes_no_values;
4036
+	}
4037
+
4038
+
4039
+	/**
4040
+	 * @return string
4041
+	 * @throws ReflectionException
4042
+	 * @since $VID:$
4043
+	 */
4044
+	protected function _get_dir()
4045
+	{
4046
+		$reflector = new ReflectionClass(get_class($this));
4047
+		return dirname($reflector->getFileName());
4048
+	}
4049
+
4050
+
4051
+	/**
4052
+	 * A helper for getting a "next link".
4053
+	 *
4054
+	 * @param string $url   The url to link to
4055
+	 * @param string $class The class to use.
4056
+	 * @return string
4057
+	 */
4058
+	protected function _next_link($url, $class = 'dashicons dashicons-arrow-right')
4059
+	{
4060
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4061
+	}
4062
+
4063
+
4064
+	/**
4065
+	 * A helper for getting a "previous link".
4066
+	 *
4067
+	 * @param string $url   The url to link to
4068
+	 * @param string $class The class to use.
4069
+	 * @return string
4070
+	 */
4071
+	protected function _previous_link($url, $class = 'dashicons dashicons-arrow-left')
4072
+	{
4073
+		return '<a class="' . $class . '" href="' . $url . '"></a>';
4074
+	}
4075
+
4076
+
4077
+
4078
+
4079
+
4080
+
4081
+
4082
+	// below are some messages related methods that should be available across the EE_Admin system.  Note, these methods are NOT page specific
4083
+
4084
+
4085
+	/**
4086
+	 * This processes an request to resend a registration and assumes we have a _REG_ID for doing so. So if the caller
4087
+	 * 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
4088
+	 * _req_data array.
4089
+	 *
4090
+	 * @return bool success/fail
4091
+	 * @throws EE_Error
4092
+	 * @throws InvalidArgumentException
4093
+	 * @throws ReflectionException
4094
+	 * @throws InvalidDataTypeException
4095
+	 * @throws InvalidInterfaceException
4096
+	 */
4097
+	protected function _process_resend_registration()
4098
+	{
4099
+		$this->_template_args['success'] = EED_Messages::process_resend($this->_req_data);
4100
+		do_action(
4101
+			'AHEE__EE_Admin_Page___process_resend_registration',
4102
+			$this->_template_args['success'],
4103
+			$this->_req_data
4104
+		);
4105
+		return $this->_template_args['success'];
4106
+	}
4107
+
4108
+
4109
+	/**
4110
+	 * This automatically processes any payment message notifications when manual payment has been applied.
4111
+	 *
4112
+	 * @param EE_Payment $payment
4113
+	 * @return bool success/fail
4114
+	 */
4115
+	protected function _process_payment_notification(EE_Payment $payment)
4116
+	{
4117
+		add_filter('FHEE__EE_Payment_Processor__process_registration_payments__display_notifications', '__return_true');
4118
+		do_action('AHEE__EE_Admin_Page___process_admin_payment_notification', $payment);
4119
+		$this->_template_args['success'] = apply_filters(
4120
+			'FHEE__EE_Admin_Page___process_admin_payment_notification__success',
4121
+			false,
4122
+			$payment
4123
+		);
4124
+		return $this->_template_args['success'];
4125
+	}
4126 4126
 }
Please login to merge, or discard this patch.
languages/event_espresso-translations-js.php 1 patch
Spacing   +416 added lines, -416 removed lines patch added patch discarded remove patch
@@ -2,261 +2,261 @@  discard block
 block discarded – undo
2 2
 /* THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY. */
3 3
 $generated_i18n_strings = array(
4 4
 	// Reference: packages/adapters/src/Pagination/constants.ts:6
5
-	__( '2', 'event_espresso' ),
5
+	__('2', 'event_espresso'),
6 6
 
7 7
 	// Reference: packages/adapters/src/Pagination/constants.ts:7
8
-	__( '6', 'event_espresso' ),
8
+	__('6', 'event_espresso'),
9 9
 
10 10
 	// Reference: packages/adapters/src/Pagination/constants.ts:8
11
-	__( '12', 'event_espresso' ),
11
+	__('12', 'event_espresso'),
12 12
 
13 13
 	// Reference: packages/adapters/src/Pagination/constants.ts:9
14
-	__( '24', 'event_espresso' ),
14
+	__('24', 'event_espresso'),
15 15
 
16 16
 	// Reference: packages/adapters/src/Pagination/constants.ts:10
17
-	__( '48', 'event_espresso' ),
17
+	__('48', 'event_espresso'),
18 18
 
19 19
 	// Reference: domains/blocks/src/components/AvatarImage.tsx:27
20
-	__( 'contact avatar', 'event_espresso' ),
20
+	__('contact avatar', 'event_espresso'),
21 21
 
22 22
 	// Reference: domains/blocks/src/components/OrderByControl.tsx:13
23
-	__( 'Order by', 'event_espresso' ),
23
+	__('Order by', 'event_espresso'),
24 24
 
25 25
 	// Reference: domains/blocks/src/components/RegStatusControl.tsx:18
26 26
 	// Reference: domains/blocks/src/event-attendees/controls/SelectStatus.tsx:12
27
-	__( 'Select Registration Status', 'event_espresso' ),
27
+	__('Select Registration Status', 'event_espresso'),
28 28
 
29 29
 	// Reference: domains/blocks/src/components/SortOrderControl.tsx:15
30
-	__( 'Ascending', 'event_espresso' ),
30
+	__('Ascending', 'event_espresso'),
31 31
 
32 32
 	// Reference: domains/blocks/src/components/SortOrderControl.tsx:19
33
-	__( 'Descending', 'event_espresso' ),
33
+	__('Descending', 'event_espresso'),
34 34
 
35 35
 	// Reference: domains/blocks/src/components/SortOrderControl.tsx:25
36
-	__( 'Sort order:', 'event_espresso' ),
36
+	__('Sort order:', 'event_espresso'),
37 37
 
38 38
 	// Reference: domains/blocks/src/event-attendees/AttendeesDisplay.tsx:40
39
-	__( 'There was some error fetching attendees list', 'event_espresso' ),
39
+	__('There was some error fetching attendees list', 'event_espresso'),
40 40
 
41 41
 	// Reference: domains/blocks/src/event-attendees/AttendeesDisplay.tsx:46
42
-	__( 'To get started, select what event you want to show attendees from in the block settings.', 'event_espresso' ),
42
+	__('To get started, select what event you want to show attendees from in the block settings.', 'event_espresso'),
43 43
 
44 44
 	// Reference: domains/blocks/src/event-attendees/AttendeesDisplay.tsx:52
45
-	__( 'There are no attendees for selected options.', 'event_espresso' ),
45
+	__('There are no attendees for selected options.', 'event_espresso'),
46 46
 
47 47
 	// Reference: domains/blocks/src/event-attendees/controls/ArchiveSettings.tsx:11
48
-	__( 'Display on Archives', 'event_espresso' ),
48
+	__('Display on Archives', 'event_espresso'),
49 49
 
50 50
 	// Reference: domains/blocks/src/event-attendees/controls/ArchiveSettings.tsx:16
51
-	__( 'Attendees are shown whenever this post is listed in an archive view.', 'event_espresso' ),
51
+	__('Attendees are shown whenever this post is listed in an archive view.', 'event_espresso'),
52 52
 
53 53
 	// Reference: domains/blocks/src/event-attendees/controls/ArchiveSettings.tsx:17
54
-	__( 'Attendees are hidden whenever this post is listed in an archive view.', 'event_espresso' ),
54
+	__('Attendees are hidden whenever this post is listed in an archive view.', 'event_espresso'),
55 55
 
56 56
 	// Reference: domains/blocks/src/event-attendees/controls/AttendeeLimit.tsx:28
57
-	__( 'Number of Attendees to Display:', 'event_espresso' ),
57
+	__('Number of Attendees to Display:', 'event_espresso'),
58 58
 
59 59
 	// Reference: domains/blocks/src/event-attendees/controls/AttendeeLimit.tsx:33
60 60
 	/* translators: %d attendees count */
61
-	_n_noop( 'Used to adjust the number of attendees displayed (There is %d total attendee for the current filter settings).', 'Used to adjust the number of attendees displayed (There are %d total attendees for the current filter settings).', 'event_espresso' ),
61
+	_n_noop('Used to adjust the number of attendees displayed (There is %d total attendee for the current filter settings).', 'Used to adjust the number of attendees displayed (There are %d total attendees for the current filter settings).', 'event_espresso'),
62 62
 
63 63
 	// Reference: domains/blocks/src/event-attendees/controls/GravatarSettings.tsx:26
64
-	__( 'Display Gravatar', 'event_espresso' ),
64
+	__('Display Gravatar', 'event_espresso'),
65 65
 
66 66
 	// Reference: domains/blocks/src/event-attendees/controls/GravatarSettings.tsx:31
67
-	__( 'Gravatar images are shown for each attendee.', 'event_espresso' ),
67
+	__('Gravatar images are shown for each attendee.', 'event_espresso'),
68 68
 
69 69
 	// Reference: domains/blocks/src/event-attendees/controls/GravatarSettings.tsx:32
70
-	__( 'No gravatar images are shown for each attendee.', 'event_espresso' ),
70
+	__('No gravatar images are shown for each attendee.', 'event_espresso'),
71 71
 
72 72
 	// Reference: domains/blocks/src/event-attendees/controls/GravatarSettings.tsx:37
73
-	__( 'Size of Gravatar', 'event_espresso' ),
73
+	__('Size of Gravatar', 'event_espresso'),
74 74
 
75 75
 	// Reference: domains/blocks/src/event-attendees/controls/SelectDatetime.tsx:21
76
-	__( 'Select Datetime', 'event_espresso' ),
76
+	__('Select Datetime', 'event_espresso'),
77 77
 
78 78
 	// Reference: domains/blocks/src/event-attendees/controls/SelectEvent.tsx:21
79
-	__( 'Select Event', 'event_espresso' ),
79
+	__('Select Event', 'event_espresso'),
80 80
 
81 81
 	// Reference: domains/blocks/src/event-attendees/controls/SelectOrderBy.tsx:10
82
-	__( 'Attendee id', 'event_espresso' ),
82
+	__('Attendee id', 'event_espresso'),
83 83
 
84 84
 	// Reference: domains/blocks/src/event-attendees/controls/SelectOrderBy.tsx:14
85
-	__( 'Last name only', 'event_espresso' ),
85
+	__('Last name only', 'event_espresso'),
86 86
 
87 87
 	// Reference: domains/blocks/src/event-attendees/controls/SelectOrderBy.tsx:18
88
-	__( 'First name only', 'event_espresso' ),
88
+	__('First name only', 'event_espresso'),
89 89
 
90 90
 	// Reference: domains/blocks/src/event-attendees/controls/SelectOrderBy.tsx:22
91
-	__( 'First, then Last name', 'event_espresso' ),
91
+	__('First, then Last name', 'event_espresso'),
92 92
 
93 93
 	// Reference: domains/blocks/src/event-attendees/controls/SelectOrderBy.tsx:26
94
-	__( 'Last, then First name', 'event_espresso' ),
94
+	__('Last, then First name', 'event_espresso'),
95 95
 
96 96
 	// Reference: domains/blocks/src/event-attendees/controls/SelectOrderBy.tsx:40
97
-	__( 'Order Attendees by:', 'event_espresso' ),
97
+	__('Order Attendees by:', 'event_espresso'),
98 98
 
99 99
 	// Reference: domains/blocks/src/event-attendees/controls/SelectTicket.tsx:21
100
-	__( 'Select Ticket', 'event_espresso' ),
100
+	__('Select Ticket', 'event_espresso'),
101 101
 
102 102
 	// Reference: domains/blocks/src/event-attendees/controls/index.tsx:22
103
-	__( 'Filter By Settings', 'event_espresso' ),
103
+	__('Filter By Settings', 'event_espresso'),
104 104
 
105 105
 	// Reference: domains/blocks/src/event-attendees/controls/index.tsx:37
106
-	__( 'Gravatar Setttings', 'event_espresso' ),
106
+	__('Gravatar Setttings', 'event_espresso'),
107 107
 
108 108
 	// Reference: domains/blocks/src/event-attendees/controls/index.tsx:40
109
-	__( 'Archive Settings', 'event_espresso' ),
109
+	__('Archive Settings', 'event_espresso'),
110 110
 
111 111
 	// Reference: domains/blocks/src/event-attendees/index.tsx:10
112
-	__( 'Event Attendees', 'event_espresso' ),
112
+	__('Event Attendees', 'event_espresso'),
113 113
 
114 114
 	// Reference: domains/blocks/src/event-attendees/index.tsx:11
115
-	__( 'Displays a list of people that have registered for the specified event', 'event_espresso' ),
115
+	__('Displays a list of people that have registered for the specified event', 'event_espresso'),
116 116
 
117 117
 	// Reference: domains/blocks/src/event-attendees/index.tsx:14
118
-	__( 'event', 'event_espresso' ),
118
+	__('event', 'event_espresso'),
119 119
 
120 120
 	// Reference: domains/blocks/src/event-attendees/index.tsx:14
121
-	__( 'attendees', 'event_espresso' ),
121
+	__('attendees', 'event_espresso'),
122 122
 
123 123
 	// Reference: domains/blocks/src/event-attendees/index.tsx:14
124
-	__( 'list', 'event_espresso' ),
124
+	__('list', 'event_espresso'),
125 125
 
126 126
 	// Reference: domains/blocks/src/services/utils.ts:11
127
-	__( 'Loading…', 'event_espresso' ),
127
+	__('Loading…', 'event_espresso'),
128 128
 
129 129
 	// Reference: domains/blocks/src/services/utils.ts:19
130 130
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:32
131
-	__( 'Error', 'event_espresso' ),
131
+	__('Error', 'event_espresso'),
132 132
 
133 133
 	// Reference: domains/blocks/src/services/utils.ts:26
134
-	__( 'Select…', 'event_espresso' ),
134
+	__('Select…', 'event_espresso'),
135 135
 
136 136
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:11
137 137
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/config.ts:13
138
-	__( 'Active', 'event_espresso' ),
138
+	__('Active', 'event_espresso'),
139 139
 
140 140
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:12
141 141
 	// Reference: packages/predicates/src/registration/statusOptions.ts:10
142
-	__( 'Cancelled', 'event_espresso' ),
142
+	__('Cancelled', 'event_espresso'),
143 143
 
144 144
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:13
145 145
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/config.ts:15
146 146
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/config.ts:14
147
-	__( 'Expired', 'event_espresso' ),
147
+	__('Expired', 'event_espresso'),
148 148
 
149 149
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:14
150
-	__( 'Inactive', 'event_espresso' ),
150
+	__('Inactive', 'event_espresso'),
151 151
 
152 152
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:15
153
-	__( 'Postponed', 'event_espresso' ),
153
+	__('Postponed', 'event_espresso'),
154 154
 
155 155
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:16
156
-	__( 'SoldOut', 'event_espresso' ),
156
+	__('SoldOut', 'event_espresso'),
157 157
 
158 158
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:17
159 159
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/config.ts:17
160
-	__( 'Upcoming', 'event_espresso' ),
160
+	__('Upcoming', 'event_espresso'),
161 161
 
162 162
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/ActiveStatus.tsx:37
163
-	__( 'Active Status', 'event_espresso' ),
163
+	__('Active Status', 'event_espresso'),
164 164
 
165 165
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/AltRegPage.tsx:36
166
-	__( 'Alternative Registration Page', 'event_espresso' ),
166
+	__('Alternative Registration Page', 'event_espresso'),
167 167
 
168 168
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/DefaultRegistrationStatus.tsx:30
169
-	__( 'Default Registration Status', 'event_espresso' ),
169
+	__('Default Registration Status', 'event_espresso'),
170 170
 
171 171
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/Donations.tsx:21
172
-	__( 'Disable Donations', 'event_espresso' ),
172
+	__('Disable Donations', 'event_espresso'),
173 173
 
174 174
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/Donations.tsx:21
175
-	__( 'Enable Donations', 'event_espresso' ),
175
+	__('Enable Donations', 'event_espresso'),
176 176
 
177 177
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/EventManager.tsx:23
178
-	__( 'Event Manager', 'event_espresso' ),
178
+	__('Event Manager', 'event_espresso'),
179 179
 
180 180
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/EventPhoneNumber.tsx:28
181
-	__( 'Event Phone Number', 'event_espresso' ),
181
+	__('Event Phone Number', 'event_espresso'),
182 182
 
183 183
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/MaxRegistrations.tsx:30
184
-	__( 'Maximum Number of Registrations Allowed per Transaction', 'event_espresso' ),
184
+	__('Maximum Number of Registrations Allowed per Transaction', 'event_espresso'),
185 185
 
186 186
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/TicketSelector.tsx:22
187
-	__( 'hide ticket selector', 'event_espresso' ),
187
+	__('hide ticket selector', 'event_espresso'),
188 188
 
189 189
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/TicketSelector.tsx:22
190
-	__( 'show ticket selector', 'event_espresso' ),
190
+	__('show ticket selector', 'event_espresso'),
191 191
 
192 192
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/TicketSelector.tsx:28
193
-	__( 'Display Ticket Selector', 'event_espresso' ),
193
+	__('Display Ticket Selector', 'event_espresso'),
194 194
 
195 195
 	// Reference: domains/eventEditor/src/ui/EventRegistrationOptions/index.tsx:21
196
-	__( 'Registration Options', 'event_espresso' ),
196
+	__('Registration Options', 'event_espresso'),
197 197
 
198 198
 	// Reference: domains/eventEditor/src/ui/datetimes/DateRegistrationsLink.tsx:17
199
-	__( 'view ALL registrations for this date.', 'event_espresso' ),
199
+	__('view ALL registrations for this date.', 'event_espresso'),
200 200
 
201 201
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/formValidation.ts:15
202 202
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/formValidation.ts:15
203
-	__( 'Name is required', 'event_espresso' ),
203
+	__('Name is required', 'event_espresso'),
204 204
 
205 205
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/formValidation.ts:16
206 206
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/formValidation.ts:12
207 207
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/formValidation.ts:16
208 208
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/formValidation.ts:12
209
-	__( 'Name must be at least three characters', 'event_espresso' ),
209
+	__('Name must be at least three characters', 'event_espresso'),
210 210
 
211 211
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/multiStep/Container.tsx:22
212 212
 	/* translators: %s datetime id */
213
-	__( 'Edit datetime %s', 'event_espresso' ),
213
+	__('Edit datetime %s', 'event_espresso'),
214 214
 
215 215
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/multiStep/Container.tsx:25
216
-	__( 'New Datetime', 'event_espresso' ),
216
+	__('New Datetime', 'event_espresso'),
217 217
 
218 218
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/multiStep/ContentBody.tsx:40
219
-	__( 'Save and assign tickets', 'event_espresso' ),
219
+	__('Save and assign tickets', 'event_espresso'),
220 220
 
221 221
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:11
222
-	__( 'primary information about the date', 'event_espresso' ),
222
+	__('primary information about the date', 'event_espresso'),
223 223
 
224 224
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:11
225
-	__( 'Date Details', 'event_espresso' ),
225
+	__('Date Details', 'event_espresso'),
226 226
 
227 227
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:12
228 228
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:17
229
-	__( 'relations between tickets and dates', 'event_espresso' ),
229
+	__('relations between tickets and dates', 'event_espresso'),
230 230
 
231 231
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/multiStep/DateFormSteps.tsx:12
232
-	__( 'Assign Tickets', 'event_espresso' ),
232
+	__('Assign Tickets', 'event_espresso'),
233 233
 
234 234
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:107
235 235
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:108
236 236
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:119
237 237
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:108
238
-	__( 'Details', 'event_espresso' ),
238
+	__('Details', 'event_espresso'),
239 239
 
240 240
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:111
241 241
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:112
242 242
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:75
243
-	__( 'Capacity', 'event_espresso' ),
243
+	__('Capacity', 'event_espresso'),
244 244
 
245 245
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:116
246
-	__( 'The maximum number of registrants that can attend the event at this particular date.', 'event_espresso' ),
246
+	__('The maximum number of registrants that can attend the event at this particular date.', 'event_espresso'),
247 247
 
248 248
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:120
249
-	__( 'Set to 0 to close registration or leave blank for no limit.', 'event_espresso' ),
249
+	__('Set to 0 to close registration or leave blank for no limit.', 'event_espresso'),
250 250
 
251 251
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:125
252 252
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:198
253
-	__( 'Trash', 'event_espresso' ),
253
+	__('Trash', 'event_espresso'),
254 254
 
255 255
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:69
256 256
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:45
257 257
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:81
258 258
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:45
259
-	__( 'Basics', 'event_espresso' ),
259
+	__('Basics', 'event_espresso'),
260 260
 
261 261
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:73
262 262
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:49
@@ -264,212 +264,212 @@  discard block
 block discarded – undo
264 264
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:85
265 265
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:49
266 266
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:42
267
-	__( 'Name', 'event_espresso' ),
267
+	__('Name', 'event_espresso'),
268 268
 
269 269
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:80
270 270
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:55
271 271
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:92
272 272
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:55
273 273
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:41
274
-	__( 'Description', 'event_espresso' ),
274
+	__('Description', 'event_espresso'),
275 275
 
276 276
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:88
277 277
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:63
278 278
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:63
279
-	__( 'Dates', 'event_espresso' ),
279
+	__('Dates', 'event_espresso'),
280 280
 
281 281
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:92
282 282
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:52
283 283
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:104
284
-	__( 'Start Date', 'event_espresso' ),
284
+	__('Start Date', 'event_espresso'),
285 285
 
286 286
 	// Reference: domains/eventEditor/src/ui/datetimes/dateForm/useDateFormConfig.ts:98
287 287
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:63
288 288
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:110
289
-	__( 'End Date', 'event_espresso' ),
289
+	__('End Date', 'event_espresso'),
290 290
 
291 291
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/DatesList.tsx:34
292 292
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/TableView.tsx:42
293
-	__( 'Event Dates', 'event_espresso' ),
293
+	__('Event Dates', 'event_espresso'),
294 294
 
295 295
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/DatesList.tsx:37
296
-	__( 'loading event dates…', 'event_espresso' ),
296
+	__('loading event dates…', 'event_espresso'),
297 297
 
298 298
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/DatesListButtons.tsx:22
299
-	__( 'Ticket Assignments', 'event_espresso' ),
299
+	__('Ticket Assignments', 'event_espresso'),
300 300
 
301 301
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:27
302
-	__( 'Number of related tickets', 'event_espresso' ),
302
+	__('Number of related tickets', 'event_espresso'),
303 303
 
304 304
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:28
305
-	__( 'There are no tickets assigned to this datetime. Please click the ticket icon to update the assignments.', 'event_espresso' ),
305
+	__('There are no tickets assigned to this datetime. Please click the ticket icon to update the assignments.', 'event_espresso'),
306 306
 
307 307
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/AssignTicketsButton.tsx:42
308
-	__( 'assign tickets', 'event_espresso' ),
308
+	__('assign tickets', 'event_espresso'),
309 309
 
310 310
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:18
311
-	__( 'Permanently delete Datetime?', 'event_espresso' ),
311
+	__('Permanently delete Datetime?', 'event_espresso'),
312 312
 
313 313
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:18
314
-	__( 'Move Datetime to Trash?', 'event_espresso' ),
314
+	__('Move Datetime to Trash?', 'event_espresso'),
315 315
 
316 316
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:20
317
-	__( 'Are you sure you want to permanently delete this datetime? This action is permanent and can not be undone.', 'event_espresso' ),
317
+	__('Are you sure you want to permanently delete this datetime? This action is permanent and can not be undone.', 'event_espresso'),
318 318
 
319 319
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:23
320
-	__( 'Are you sure you want to move this datetime to the trash? You can "untrash" this datetime later if you need to.', 'event_espresso' ),
320
+	__('Are you sure you want to move this datetime to the trash? You can "untrash" this datetime later if you need to.', 'event_espresso'),
321 321
 
322 322
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:33
323
-	__( 'event date main menu', 'event_espresso' ),
323
+	__('event date main menu', 'event_espresso'),
324 324
 
325 325
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:37
326 326
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:33
327
-	__( 'delete permanently', 'event_espresso' ),
327
+	__('delete permanently', 'event_espresso'),
328 328
 
329 329
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:37
330
-	__( 'trash datetime', 'event_espresso' ),
330
+	__('trash datetime', 'event_espresso'),
331 331
 
332 332
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:46
333
-	__( 'edit datetime', 'event_espresso' ),
333
+	__('edit datetime', 'event_espresso'),
334 334
 
335 335
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/actionsMenu/dropdown/DateMainMenu.tsx:47
336
-	__( 'copy datetime', 'event_espresso' ),
336
+	__('copy datetime', 'event_espresso'),
337 337
 
338 338
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:30
339
-	__( 'edit datetime details', 'event_espresso' ),
339
+	__('edit datetime details', 'event_espresso'),
340 340
 
341 341
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:34
342
-	__( 'delete datetimes', 'event_espresso' ),
342
+	__('delete datetimes', 'event_espresso'),
343 343
 
344 344
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/actions/Actions.tsx:34
345
-	__( 'trash datetimes', 'event_espresso' ),
345
+	__('trash datetimes', 'event_espresso'),
346 346
 
347 347
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:13
348
-	__( 'Are you sure you want to permanently delete these datetimes? This action can NOT be undone!', 'event_espresso' ),
348
+	__('Are you sure you want to permanently delete these datetimes? This action can NOT be undone!', 'event_espresso'),
349 349
 
350 350
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:14
351
-	__( 'Are you sure you want to trash these datetimes?', 'event_espresso' ),
351
+	__('Are you sure you want to trash these datetimes?', 'event_espresso'),
352 352
 
353 353
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:15
354
-	__( 'Delete datetimes permanently', 'event_espresso' ),
354
+	__('Delete datetimes permanently', 'event_espresso'),
355 355
 
356 356
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/delete/Delete.tsx:15
357
-	__( 'Trash datetimes', 'event_espresso' ),
357
+	__('Trash datetimes', 'event_espresso'),
358 358
 
359 359
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/EditDetails.tsx:22
360
-	__( 'Bulk edit date details', 'event_espresso' ),
360
+	__('Bulk edit date details', 'event_espresso'),
361 361
 
362 362
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/EditDetails.tsx:23
363
-	__( 'any changes will be applied to ALL of the selected dates.', 'event_espresso' ),
363
+	__('any changes will be applied to ALL of the selected dates.', 'event_espresso'),
364 364
 
365 365
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:67
366 366
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:67
367
-	__( 'Shift dates', 'event_espresso' ),
367
+	__('Shift dates', 'event_espresso'),
368 368
 
369 369
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:92
370 370
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:92
371
-	__( 'earlier', 'event_espresso' ),
371
+	__('earlier', 'event_espresso'),
372 372
 
373 373
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/bulkEdit/details/useBulkEditFormConfig.ts:96
374 374
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:96
375
-	__( 'later', 'event_espresso' ),
375
+	__('later', 'event_espresso'),
376 376
 
377 377
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/cardView/DateCapacity.tsx:35
378
-	__( 'edit capacity (registration limit)…', 'event_espresso' ),
378
+	__('edit capacity (registration limit)…', 'event_espresso'),
379 379
 
380 380
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:37
381
-	__( 'Edit Event Date', 'event_espresso' ),
381
+	__('Edit Event Date', 'event_espresso'),
382 382
 
383 383
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/cardView/DateCardSidebar.tsx:40
384
-	__( 'edit start and end dates', 'event_espresso' ),
384
+	__('edit start and end dates', 'event_espresso'),
385 385
 
386 386
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:14
387 387
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:14
388
-	__( 'sold', 'event_espresso' ),
388
+	__('sold', 'event_espresso'),
389 389
 
390 390
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:27
391
-	__( 'capacity', 'event_espresso' ),
391
+	__('capacity', 'event_espresso'),
392 392
 
393 393
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/cardView/DateDetailsPanel.tsx:33
394 394
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:32
395
-	__( 'reg list', 'event_espresso' ),
395
+	__('reg list', 'event_espresso'),
396 396
 
397 397
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/cardView/Details.tsx:44
398 398
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/cardView/Details.tsx:40
399
-	__( 'Edit description', 'event_espresso' ),
399
+	__('Edit description', 'event_espresso'),
400 400
 
401 401
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/cardView/Details.tsx:45
402 402
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/cardView/Details.tsx:41
403
-	__( 'edit description…', 'event_espresso' ),
403
+	__('edit description…', 'event_espresso'),
404 404
 
405 405
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/config.ts:14
406 406
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/config.ts:13
407
-	__( 'Trashed', 'event_espresso' ),
407
+	__('Trashed', 'event_espresso'),
408 408
 
409 409
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/config.ts:16
410 410
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/config.ts:16
411
-	__( 'Sold Out', 'event_espresso' ),
411
+	__('Sold Out', 'event_espresso'),
412 412
 
413 413
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/editable/EditableName.tsx:17
414 414
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/editable/EditableName.tsx:27
415
-	__( 'edit title…', 'event_espresso' ),
415
+	__('edit title…', 'event_espresso'),
416 416
 
417 417
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/ActiveDatesFilters.tsx:25
418 418
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/ActiveTicketsFilters.tsx:25
419
-	__( 'ON', 'event_espresso' ),
419
+	__('ON', 'event_espresso'),
420 420
 
421 421
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:10
422
-	__( 'end dates only', 'event_espresso' ),
422
+	__('end dates only', 'event_espresso'),
423 423
 
424 424
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:11
425
-	__( 'start and end dates', 'event_espresso' ),
425
+	__('start and end dates', 'event_espresso'),
426 426
 
427 427
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:16
428
-	__( 'dates above 90% capacity', 'event_espresso' ),
428
+	__('dates above 90% capacity', 'event_espresso'),
429 429
 
430 430
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:17
431
-	__( 'dates above 75% capacity', 'event_espresso' ),
431
+	__('dates above 75% capacity', 'event_espresso'),
432 432
 
433 433
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:18
434
-	__( 'dates above 50% capacity', 'event_espresso' ),
434
+	__('dates above 50% capacity', 'event_espresso'),
435 435
 
436 436
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:19
437
-	__( 'dates below 50% capacity', 'event_espresso' ),
437
+	__('dates below 50% capacity', 'event_espresso'),
438 438
 
439 439
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:23
440
-	__( 'all dates', 'event_espresso' ),
440
+	__('all dates', 'event_espresso'),
441 441
 
442 442
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:24
443
-	__( 'all active and upcoming', 'event_espresso' ),
443
+	__('all active and upcoming', 'event_espresso'),
444 444
 
445 445
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:25
446
-	__( 'active dates only', 'event_espresso' ),
446
+	__('active dates only', 'event_espresso'),
447 447
 
448 448
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:26
449
-	__( 'upcoming dates only', 'event_espresso' ),
449
+	__('upcoming dates only', 'event_espresso'),
450 450
 
451 451
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:27
452
-	__( 'next active or upcoming only', 'event_espresso' ),
452
+	__('next active or upcoming only', 'event_espresso'),
453 453
 
454 454
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:28
455
-	__( 'sold out dates only', 'event_espresso' ),
455
+	__('sold out dates only', 'event_espresso'),
456 456
 
457 457
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:29
458
-	__( 'recently expired dates', 'event_espresso' ),
458
+	__('recently expired dates', 'event_espresso'),
459 459
 
460 460
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:30
461
-	__( 'all expired dates', 'event_espresso' ),
461
+	__('all expired dates', 'event_espresso'),
462 462
 
463 463
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:31
464
-	__( 'trashed dates only', 'event_espresso' ),
464
+	__('trashed dates only', 'event_espresso'),
465 465
 
466 466
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:35
467 467
 	// Reference: packages/dates/src/DateRangePicker/DateRangePickerLegend.tsx:10
468 468
 	// Reference: packages/dates/src/DateRangePicker/index.tsx:41
469
-	__( 'start date', 'event_espresso' ),
469
+	__('start date', 'event_espresso'),
470 470
 
471 471
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:36
472
-	__( 'name', 'event_espresso' ),
472
+	__('name', 'event_espresso'),
473 473
 
474 474
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:37
475 475
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:38
@@ -477,96 +477,96 @@  discard block
 block discarded – undo
477 477
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/table/HeaderCell.tsx:20
478 478
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:36
479 479
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:23
480
-	__( 'ID', 'event_espresso' ),
480
+	__('ID', 'event_espresso'),
481 481
 
482 482
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:38
483 483
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:47
484
-	__( 'custom order', 'event_espresso' ),
484
+	__('custom order', 'event_espresso'),
485 485
 
486 486
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:42
487 487
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:52
488
-	__( 'display', 'event_espresso' ),
488
+	__('display', 'event_espresso'),
489 489
 
490 490
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:43
491
-	__( 'recurrence', 'event_espresso' ),
491
+	__('recurrence', 'event_espresso'),
492 492
 
493 493
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:44
494 494
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:54
495
-	__( 'sales', 'event_espresso' ),
495
+	__('sales', 'event_espresso'),
496 496
 
497 497
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:45
498 498
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:56
499
-	__( 'sort by', 'event_espresso' ),
499
+	__('sort by', 'event_espresso'),
500 500
 
501 501
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:46
502 502
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:55
503 503
 	// Reference: packages/components/src/EntityList/filterBar/EntityListFilterBar.tsx:73
504
-	__( 'search', 'event_espresso' ),
504
+	__('search', 'event_espresso'),
505 505
 
506 506
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:47
507 507
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:57
508
-	__( 'status', 'event_espresso' ),
508
+	__('status', 'event_espresso'),
509 509
 
510 510
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/filterBar/controls/options.ts:9
511
-	__( 'start dates only', 'event_espresso' ),
511
+	__('start dates only', 'event_espresso'),
512 512
 
513 513
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:20
514 514
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/newDateOptions/OptionsPopover.tsx:14
515 515
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/newDateOptions/OptionsPopoverButton.tsx:11
516
-	__( 'Add New Date', 'event_espresso' ),
516
+	__('Add New Date', 'event_espresso'),
517 517
 
518 518
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:20
519
-	__( 'Add Single Date', 'event_espresso' ),
519
+	__('Add Single Date', 'event_espresso'),
520 520
 
521 521
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:34
522
-	__( 'Add a single date that only occurs once', 'event_espresso' ),
522
+	__('Add a single date that only occurs once', 'event_espresso'),
523 523
 
524 524
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/newDateOptions/AddSingleDate.tsx:36
525
-	__( 'Single Date', 'event_espresso' ),
525
+	__('Single Date', 'event_espresso'),
526 526
 
527 527
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:105
528 528
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:103
529 529
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:53
530
-	__( 'Actions', 'event_espresso' ),
530
+	__('Actions', 'event_espresso'),
531 531
 
532 532
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:53
533
-	__( 'Start', 'event_espresso' ),
533
+	__('Start', 'event_espresso'),
534 534
 
535 535
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:64
536
-	__( 'End', 'event_espresso' ),
536
+	__('End', 'event_espresso'),
537 537
 
538 538
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:76
539
-	__( 'Cap', 'event_espresso' ),
539
+	__('Cap', 'event_espresso'),
540 540
 
541 541
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:84
542 542
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:85
543
-	__( 'Sold', 'event_espresso' ),
543
+	__('Sold', 'event_espresso'),
544 544
 
545 545
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:93
546
-	__( 'Reg list', 'event_espresso' ),
546
+	__('Reg list', 'event_espresso'),
547 547
 
548 548
 	// Reference: domains/eventEditor/src/ui/datetimes/datesList/tableView/useHeaderRowGenerator.tsx:94
549 549
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:95
550
-	__( 'Regs', 'event_espresso' ),
550
+	__('Regs', 'event_espresso'),
551 551
 
552 552
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:18
553
-	__( 'Tickets must always have at least one date assigned to them but one or more of the tickets below does not have any. Please correct the assignments for the highlighted cells.', 'event_espresso' ),
553
+	__('Tickets must always have at least one date assigned to them but one or more of the tickets below does not have any. Please correct the assignments for the highlighted cells.', 'event_espresso'),
554 554
 
555 555
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/ErrorMessage.tsx:22
556
-	__( 'Event Dates must always have at least one Ticket assigned to them but one or more of the Event Dates below does not have any. Please correct the assignments for the highlighted cells.', 'event_espresso' ),
556
+	__('Event Dates must always have at least one Ticket assigned to them but one or more of the Event Dates below does not have any. Please correct the assignments for the highlighted cells.', 'event_espresso'),
557 557
 
558 558
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:25
559 559
 	/* translators: %d entity id, %s entity name */
560
-	__( 'Ticket Assignment Manager for Datetime: %1$d - %2$s', 'event_espresso' ),
560
+	__('Ticket Assignment Manager for Datetime: %1$d - %2$s', 'event_espresso'),
561 561
 
562 562
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/ModalContainer.tsx:32
563 563
 	/* translators: %d entity id, %s entity name */
564
-	__( 'Ticket Assignment Manager for Ticket: %1$d - %2$s', 'event_espresso' ),
564
+	__('Ticket Assignment Manager for Ticket: %1$d - %2$s', 'event_espresso'),
565 565
 
566 566
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/TicketAssignmentsManagerModal/buttons/useCancelButtonProps.tsx:18
567 567
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:16
568 568
 	// Reference: packages/components/src/Modal/useCancelButtonProps.tsx:10
569
-	__( 'Cancel', 'event_espresso' ),
569
+	__('Cancel', 'event_espresso'),
570 570
 
571 571
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/TicketAssignmentsManagerModal/buttons/useSubmitButtonProps.tsx:25
572 572
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:17
@@ -575,784 +575,784 @@  discard block
 block discarded – undo
575 575
 	// Reference: packages/components/src/bulkEdit/details/Submit.tsx:38
576 576
 	// Reference: packages/form/src/Submit.tsx:26
577 577
 	// Reference: packages/tpc/src/buttons/useSubmitButtonProps.tsx:25
578
-	__( 'Submit', 'event_espresso' ),
578
+	__('Submit', 'event_espresso'),
579 579
 
580 580
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/TicketAssignmentsManagerModal/index.tsx:32
581 581
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/table/Table.tsx:14
582
-	__( 'Ticket Assignment Manager', 'event_espresso' ),
582
+	__('Ticket Assignment Manager', 'event_espresso'),
583 583
 
584 584
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/components/table/BodyCell.tsx:24
585
-	__( 'assign ticket', 'event_espresso' ),
585
+	__('assign ticket', 'event_espresso'),
586 586
 
587 587
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/DatesByMonthControl.tsx:19
588
-	__( 'All Dates', 'event_espresso' ),
588
+	__('All Dates', 'event_espresso'),
589 589
 
590 590
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/DatesByMonthControl.tsx:26
591
-	__( 'dates by month', 'event_espresso' ),
591
+	__('dates by month', 'event_espresso'),
592 592
 
593 593
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowExpiredTicketsControl.tsx:15
594
-	__( 'show expired tickets', 'event_espresso' ),
594
+	__('show expired tickets', 'event_espresso'),
595 595
 
596 596
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowTrashedDatesControl.tsx:12
597
-	__( 'show trashed dates', 'event_espresso' ),
597
+	__('show trashed dates', 'event_espresso'),
598 598
 
599 599
 	// Reference: domains/eventEditor/src/ui/ticketAssignmentsManager/filters/controls/ShowTrashedTicketsControl.tsx:15
600
-	__( 'show trashed tickets', 'event_espresso' ),
600
+	__('show trashed tickets', 'event_espresso'),
601 601
 
602 602
 	// Reference: domains/eventEditor/src/ui/tickets/TicketRegistrationsLink.tsx:17
603
-	__( 'total registrations.', 'event_espresso' ),
603
+	__('total registrations.', 'event_espresso'),
604 604
 
605 605
 	// Reference: domains/eventEditor/src/ui/tickets/TicketRegistrationsLink.tsx:18
606
-	__( 'view ALL registrations for this ticket.', 'event_espresso' ),
606
+	__('view ALL registrations for this ticket.', 'event_espresso'),
607 607
 
608 608
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/Container.tsx:21
609 609
 	/* translators: %d ticket id */
610
-	__( 'Edit ticket %d', 'event_espresso' ),
610
+	__('Edit ticket %d', 'event_espresso'),
611 611
 
612 612
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/Container.tsx:24
613
-	__( 'New Ticket Details', 'event_espresso' ),
613
+	__('New Ticket Details', 'event_espresso'),
614 614
 
615 615
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/ContentBody.tsx:47
616
-	__( 'Set ticket prices', 'event_espresso' ),
616
+	__('Set ticket prices', 'event_espresso'),
617 617
 
618 618
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/ContentBody.tsx:54
619
-	__( 'Skip prices - assign dates', 'event_espresso' ),
619
+	__('Skip prices - assign dates', 'event_espresso'),
620 620
 
621 621
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/ContentBody.tsx:70
622
-	__( 'Save and assign dates', 'event_espresso' ),
622
+	__('Save and assign dates', 'event_espresso'),
623 623
 
624 624
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/ContentBody.tsx:83
625
-	__( 'Ticket details', 'event_espresso' ),
625
+	__('Ticket details', 'event_espresso'),
626 626
 
627 627
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:11
628
-	__( 'primary information about the ticket', 'event_espresso' ),
628
+	__('primary information about the ticket', 'event_espresso'),
629 629
 
630 630
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:11
631
-	__( 'Ticket Details', 'event_espresso' ),
631
+	__('Ticket Details', 'event_espresso'),
632 632
 
633 633
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:13
634
-	__( 'apply ticket price modifiers and taxes', 'event_espresso' ),
634
+	__('apply ticket price modifiers and taxes', 'event_espresso'),
635 635
 
636 636
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:15
637
-	__( 'Price Calculator', 'event_espresso' ),
637
+	__('Price Calculator', 'event_espresso'),
638 638
 
639 639
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/multiStep/TicketFormSteps.tsx:17
640
-	__( 'Assign Dates', 'event_espresso' ),
640
+	__('Assign Dates', 'event_espresso'),
641 641
 
642 642
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:100
643
-	__( 'Ticket Sales', 'event_espresso' ),
643
+	__('Ticket Sales', 'event_espresso'),
644 644
 
645 645
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:123
646 646
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:112
647
-	__( 'Quantity For Sale', 'event_espresso' ),
647
+	__('Quantity For Sale', 'event_espresso'),
648 648
 
649 649
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:129
650
-	__( 'The maximum number of this ticket available for sale.', 'event_espresso' ),
650
+	__('The maximum number of this ticket available for sale.', 'event_espresso'),
651 651
 
652 652
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:131
653
-	__( 'Set to 0 to stop sales, or leave blank for no limit.', 'event_espresso' ),
653
+	__('Set to 0 to stop sales, or leave blank for no limit.', 'event_espresso'),
654 654
 
655 655
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:136
656 656
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:121
657
-	__( 'Number of Uses', 'event_espresso' ),
657
+	__('Number of Uses', 'event_espresso'),
658 658
 
659 659
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:142
660
-	__( 'Controls the total number of times this ticket can be used, regardless of the number of dates it is assigned to.', 'event_espresso' ),
660
+	__('Controls the total number of times this ticket can be used, regardless of the number of dates it is assigned to.', 'event_espresso'),
661 661
 
662 662
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:146
663
-	__( 'Example: A ticket might have access to 4 different dates, but setting this field to 2 would mean that the ticket could only be used twice. Leave blank for no limit.', 'event_espresso' ),
663
+	__('Example: A ticket might have access to 4 different dates, but setting this field to 2 would mean that the ticket could only be used twice. Leave blank for no limit.', 'event_espresso'),
664 664
 
665 665
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:153
666 666
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:129
667
-	__( 'Minimum Quantity', 'event_espresso' ),
667
+	__('Minimum Quantity', 'event_espresso'),
668 668
 
669 669
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:158
670
-	__( 'The minimum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso' ),
670
+	__('The minimum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso'),
671 671
 
672 672
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:162
673
-	__( 'Leave blank for no minimum.', 'event_espresso' ),
673
+	__('Leave blank for no minimum.', 'event_espresso'),
674 674
 
675 675
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:167
676 676
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:137
677
-	__( 'Maximum Quantity', 'event_espresso' ),
677
+	__('Maximum Quantity', 'event_espresso'),
678 678
 
679 679
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:173
680
-	__( 'The maximum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso' ),
680
+	__('The maximum quantity that can be selected for this ticket. Use this to create ticket bundles or graduated pricing.', 'event_espresso'),
681 681
 
682 682
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:177
683
-	__( 'Leave blank for no maximum.', 'event_espresso' ),
683
+	__('Leave blank for no maximum.', 'event_espresso'),
684 684
 
685 685
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:182
686 686
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/useBulkEditFormConfig.ts:146
687
-	__( 'Required Ticket', 'event_espresso' ),
687
+	__('Required Ticket', 'event_espresso'),
688 688
 
689 689
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:184
690
-	__( 'If enabled, the ticket must be selected and will appear first in frontend ticket lists.', 'event_espresso' ),
690
+	__('If enabled, the ticket must be selected and will appear first in frontend ticket lists.', 'event_espresso'),
691 691
 
692 692
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:191
693
-	__( 'Default Ticket', 'event_espresso' ),
693
+	__('Default Ticket', 'event_espresso'),
694 694
 
695 695
 	// Reference: domains/eventEditor/src/ui/tickets/ticketForm/useTicketFormConfig.tsx:193
696
-	__( 'If enabled, the ticket will appear on all new events.', 'event_espresso' ),
696
+	__('If enabled, the ticket will appear on all new events.', 'event_espresso'),
697 697
 
698 698
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/TicketsList.tsx:35
699
-	__( 'Available Tickets', 'event_espresso' ),
699
+	__('Available Tickets', 'event_espresso'),
700 700
 
701 701
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/TicketsList.tsx:38
702
-	__( 'loading tickets…', 'event_espresso' ),
702
+	__('loading tickets…', 'event_espresso'),
703 703
 
704 704
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:27
705
-	__( 'Number of related dates', 'event_espresso' ),
705
+	__('Number of related dates', 'event_espresso'),
706 706
 
707 707
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:28
708
-	__( 'There are no event dates assigned to this ticket. Please click the calendar icon to update the assignments.', 'event_espresso' ),
708
+	__('There are no event dates assigned to this ticket. Please click the calendar icon to update the assignments.', 'event_espresso'),
709 709
 
710 710
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/AssignDatesButton.tsx:44
711
-	__( 'assign dates', 'event_espresso' ),
711
+	__('assign dates', 'event_espresso'),
712 712
 
713 713
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:17
714
-	__( 'Permanently delete Ticket?', 'event_espresso' ),
714
+	__('Permanently delete Ticket?', 'event_espresso'),
715 715
 
716 716
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:17
717
-	__( 'Move Ticket to Trash?', 'event_espresso' ),
717
+	__('Move Ticket to Trash?', 'event_espresso'),
718 718
 
719 719
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:19
720
-	__( 'Are you sure you want to permanently delete this ticket? This action is permanent and can not be undone.', 'event_espresso' ),
720
+	__('Are you sure you want to permanently delete this ticket? This action is permanent and can not be undone.', 'event_espresso'),
721 721
 
722 722
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:20
723
-	__( 'Are you sure you want to move this ticket to the trash? You can "untrash" this ticket later if you need to.', 'event_espresso' ),
723
+	__('Are you sure you want to move this ticket to the trash? You can "untrash" this ticket later if you need to.', 'event_espresso'),
724 724
 
725 725
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:29
726
-	__( 'ticket main menu', 'event_espresso' ),
726
+	__('ticket main menu', 'event_espresso'),
727 727
 
728 728
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:33
729
-	__( 'trash ticket', 'event_espresso' ),
729
+	__('trash ticket', 'event_espresso'),
730 730
 
731 731
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:42
732
-	__( 'edit ticket', 'event_espresso' ),
732
+	__('edit ticket', 'event_espresso'),
733 733
 
734 734
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/actionsMenu/dropdown/TicketMainMenu.tsx:43
735
-	__( 'copy ticket', 'event_espresso' ),
735
+	__('copy ticket', 'event_espresso'),
736 736
 
737 737
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:39
738 738
 	// Reference: packages/components/src/bulkEdit/BulkActions.tsx:44
739
-	__( 'bulk actions', 'event_espresso' ),
739
+	__('bulk actions', 'event_espresso'),
740 740
 
741 741
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:43
742
-	__( 'edit ticket details', 'event_espresso' ),
742
+	__('edit ticket details', 'event_espresso'),
743 743
 
744 744
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:47
745
-	__( 'delete tickets', 'event_espresso' ),
745
+	__('delete tickets', 'event_espresso'),
746 746
 
747 747
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:47
748
-	__( 'trash tickets', 'event_espresso' ),
748
+	__('trash tickets', 'event_espresso'),
749 749
 
750 750
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/actions/Actions.tsx:51
751
-	__( 'edit ticket prices', 'event_espresso' ),
751
+	__('edit ticket prices', 'event_espresso'),
752 752
 
753 753
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:13
754
-	__( 'Are you sure you want to permanently delete these tickets? This action can NOT be undone!', 'event_espresso' ),
754
+	__('Are you sure you want to permanently delete these tickets? This action can NOT be undone!', 'event_espresso'),
755 755
 
756 756
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:14
757
-	__( 'Are you sure you want to trash these tickets?', 'event_espresso' ),
757
+	__('Are you sure you want to trash these tickets?', 'event_espresso'),
758 758
 
759 759
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:15
760
-	__( 'Delete tickets permanently', 'event_espresso' ),
760
+	__('Delete tickets permanently', 'event_espresso'),
761 761
 
762 762
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/delete/Delete.tsx:15
763
-	__( 'Trash tickets', 'event_espresso' ),
763
+	__('Trash tickets', 'event_espresso'),
764 764
 
765 765
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/EditDetails.tsx:22
766
-	__( 'Bulk edit ticket details', 'event_espresso' ),
766
+	__('Bulk edit ticket details', 'event_espresso'),
767 767
 
768 768
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/details/EditDetails.tsx:23
769
-	__( 'any changes will be applied to ALL of the selected tickets.', 'event_espresso' ),
769
+	__('any changes will be applied to ALL of the selected tickets.', 'event_espresso'),
770 770
 
771 771
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/EditPrices.tsx:18
772
-	__( 'Bulk edit ticket prices', 'event_espresso' ),
772
+	__('Bulk edit ticket prices', 'event_espresso'),
773 773
 
774 774
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:19
775
-	__( 'Edit all prices together', 'event_espresso' ),
775
+	__('Edit all prices together', 'event_espresso'),
776 776
 
777 777
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:20
778
-	__( 'Edit all the selected ticket prices dynamically', 'event_espresso' ),
778
+	__('Edit all the selected ticket prices dynamically', 'event_espresso'),
779 779
 
780 780
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:24
781
-	__( 'Edit prices individually', 'event_espresso' ),
781
+	__('Edit prices individually', 'event_espresso'),
782 782
 
783 783
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/EditModeButtons.tsx:25
784
-	__( 'Edit prices for each ticket individually', 'event_espresso' ),
784
+	__('Edit prices for each ticket individually', 'event_espresso'),
785 785
 
786 786
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/buttons/FooterButtons.tsx:15
787 787
 	// Reference: packages/components/src/bulkEdit/details/Submit.tsx:45
788 788
 	// Reference: packages/form/src/ResetButton.tsx:17
789 789
 	// Reference: packages/tpc/src/buttons/useResetButtonProps.tsx:12
790
-	__( 'Reset', 'event_espresso' ),
790
+	__('Reset', 'event_espresso'),
791 791
 
792 792
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/bulkEdit/prices/editSeparately/TPCInstance.tsx:25
793 793
 	/* translators: %s ticket name */
794
-	__( 'Edit prices for Ticket: %s', 'event_espresso' ),
794
+	__('Edit prices for Ticket: %s', 'event_espresso'),
795 795
 
796 796
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:36
797
-	__( 'Edit Ticket Sale Dates', 'event_espresso' ),
797
+	__('Edit Ticket Sale Dates', 'event_espresso'),
798 798
 
799 799
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/cardView/TicketCardSidebar.tsx:38
800
-	__( 'edit ticket sales start and end dates', 'event_espresso' ),
800
+	__('edit ticket sales start and end dates', 'event_espresso'),
801 801
 
802 802
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/cardView/TicketDetailsPanel.tsx:27
803
-	__( 'quantity', 'event_espresso' ),
803
+	__('quantity', 'event_espresso'),
804 804
 
805 805
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/cardView/TicketQuantity.tsx:26
806
-	__( 'edit quantity of tickets available…', 'event_espresso' ),
806
+	__('edit quantity of tickets available…', 'event_espresso'),
807 807
 
808 808
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/config.ts:15
809 809
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:51
810
-	__( 'On Sale', 'event_espresso' ),
810
+	__('On Sale', 'event_espresso'),
811 811
 
812 812
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/config.ts:17
813
-	__( 'Pending', 'event_espresso' ),
813
+	__('Pending', 'event_espresso'),
814 814
 
815 815
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/editable/EditablePrice.tsx:30
816
-	__( 'edit ticket total…', 'event_espresso' ),
816
+	__('edit ticket total…', 'event_espresso'),
817 817
 
818 818
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/editable/EditablePrice.tsx:37
819
-	__( 'set price…', 'event_espresso' ),
819
+	__('set price…', 'event_espresso'),
820 820
 
821 821
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/IsChainedButton.tsx:24
822
-	__( 'tickets list is linked to dates list and is showing tickets for above dates only', 'event_espresso' ),
822
+	__('tickets list is linked to dates list and is showing tickets for above dates only', 'event_espresso'),
823 823
 
824 824
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/IsChainedButton.tsx:25
825
-	__( 'tickets list is unlinked and is showing tickets for all event dates', 'event_espresso' ),
825
+	__('tickets list is unlinked and is showing tickets for all event dates', 'event_espresso'),
826 826
 
827 827
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:10
828
-	__( 'ticket sales start and end dates', 'event_espresso' ),
828
+	__('ticket sales start and end dates', 'event_espresso'),
829 829
 
830 830
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:15
831
-	__( 'tickets with 90% or more sold', 'event_espresso' ),
831
+	__('tickets with 90% or more sold', 'event_espresso'),
832 832
 
833 833
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:16
834
-	__( 'tickets with 75% or more sold', 'event_espresso' ),
834
+	__('tickets with 75% or more sold', 'event_espresso'),
835 835
 
836 836
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:17
837
-	__( 'tickets with 50% or more sold', 'event_espresso' ),
837
+	__('tickets with 50% or more sold', 'event_espresso'),
838 838
 
839 839
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:19
840
-	__( 'tickets with less than 50% sold', 'event_espresso' ),
840
+	__('tickets with less than 50% sold', 'event_espresso'),
841 841
 
842 842
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:28
843
-	__( 'all tickets for all dates', 'event_espresso' ),
843
+	__('all tickets for all dates', 'event_espresso'),
844 844
 
845 845
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:29
846
-	__( 'all on sale and sale pending', 'event_espresso' ),
846
+	__('all on sale and sale pending', 'event_espresso'),
847 847
 
848 848
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:30
849
-	__( 'on sale tickets only', 'event_espresso' ),
849
+	__('on sale tickets only', 'event_espresso'),
850 850
 
851 851
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:31
852
-	__( 'sale pending tickets only', 'event_espresso' ),
852
+	__('sale pending tickets only', 'event_espresso'),
853 853
 
854 854
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:32
855
-	__( 'next on sale or sale pending only', 'event_espresso' ),
855
+	__('next on sale or sale pending only', 'event_espresso'),
856 856
 
857 857
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:33
858
-	__( 'sold out tickets only', 'event_espresso' ),
858
+	__('sold out tickets only', 'event_espresso'),
859 859
 
860 860
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:34
861
-	__( 'expired tickets only', 'event_espresso' ),
861
+	__('expired tickets only', 'event_espresso'),
862 862
 
863 863
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:35
864
-	__( 'trashed tickets only', 'event_espresso' ),
864
+	__('trashed tickets only', 'event_espresso'),
865 865
 
866 866
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:40
867
-	__( 'all tickets for above dates', 'event_espresso' ),
867
+	__('all tickets for above dates', 'event_espresso'),
868 868
 
869 869
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:44
870
-	__( 'ticket sale date', 'event_espresso' ),
870
+	__('ticket sale date', 'event_espresso'),
871 871
 
872 872
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:45
873
-	__( 'ticket name', 'event_espresso' ),
873
+	__('ticket name', 'event_espresso'),
874 874
 
875 875
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:46
876
-	__( 'ticket ID', 'event_espresso' ),
876
+	__('ticket ID', 'event_espresso'),
877 877
 
878 878
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:53
879
-	__( 'link', 'event_espresso' ),
879
+	__('link', 'event_espresso'),
880 880
 
881 881
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:8
882
-	__( 'ticket sales start date only', 'event_espresso' ),
882
+	__('ticket sales start date only', 'event_espresso'),
883 883
 
884 884
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/filterBar/controls/options.ts:9
885
-	__( 'ticket sales end date only', 'event_espresso' ),
885
+	__('ticket sales end date only', 'event_espresso'),
886 886
 
887 887
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:19
888
-	__( 'Add New Ticket', 'event_espresso' ),
888
+	__('Add New Ticket', 'event_espresso'),
889 889
 
890 890
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:31
891
-	__( 'Single Ticket', 'event_espresso' ),
891
+	__('Single Ticket', 'event_espresso'),
892 892
 
893 893
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/newTicketOptions/AddSingleTicket.tsx:33
894
-	__( 'Add a single ticket and assign the dates to it', 'event_espresso' ),
894
+	__('Add a single ticket and assign the dates to it', 'event_espresso'),
895 895
 
896 896
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/TableView.tsx:40
897
-	__( 'Tickets', 'event_espresso' ),
897
+	__('Tickets', 'event_espresso'),
898 898
 
899 899
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:50
900
-	__( 'Goes on Sale', 'event_espresso' ),
900
+	__('Goes on Sale', 'event_espresso'),
901 901
 
902 902
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:61
903
-	__( 'Sale Ends', 'event_espresso' ),
903
+	__('Sale Ends', 'event_espresso'),
904 904
 
905 905
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:62
906
-	__( 'Ends', 'event_espresso' ),
906
+	__('Ends', 'event_espresso'),
907 907
 
908 908
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:71
909
-	__( 'Price', 'event_espresso' ),
909
+	__('Price', 'event_espresso'),
910 910
 
911 911
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:78
912
-	__( 'Quantity', 'event_espresso' ),
912
+	__('Quantity', 'event_espresso'),
913 913
 
914 914
 	// Reference: domains/eventEditor/src/ui/tickets/ticketsList/tableView/useHeaderRowGenerator.tsx:94
915
-	__( 'Registrations', 'event_espresso' ),
915
+	__('Registrations', 'event_espresso'),
916 916
 
917 917
 	// Reference: domains/wpPluginsPage/src/exitSurvey/Popup.tsx:28
918
-	__( 'Do you have a moment to share why you are deactivating Event Espresso?', 'event_espresso' ),
918
+	__('Do you have a moment to share why you are deactivating Event Espresso?', 'event_espresso'),
919 919
 
920 920
 	// Reference: domains/wpPluginsPage/src/exitSurvey/Popup.tsx:39
921
-	__( 'Skip', 'event_espresso' ),
921
+	__('Skip', 'event_espresso'),
922 922
 
923 923
 	// Reference: domains/wpPluginsPage/src/exitSurvey/Popup.tsx:41
924
-	__( 'Sure I\'ll help', 'event_espresso' ),
924
+	__('Sure I\'ll help', 'event_espresso'),
925 925
 
926 926
 	// Reference: packages/adapters/src/Pagination/ItemRender.tsx:10
927
-	__( 'next', 'event_espresso' ),
927
+	__('next', 'event_espresso'),
928 928
 
929 929
 	// Reference: packages/adapters/src/Pagination/ItemRender.tsx:11
930
-	__( 'jump to previous', 'event_espresso' ),
930
+	__('jump to previous', 'event_espresso'),
931 931
 
932 932
 	// Reference: packages/adapters/src/Pagination/ItemRender.tsx:12
933
-	__( 'jump to next', 'event_espresso' ),
933
+	__('jump to next', 'event_espresso'),
934 934
 
935 935
 	// Reference: packages/adapters/src/Pagination/ItemRender.tsx:13
936
-	__( 'page', 'event_espresso' ),
936
+	__('page', 'event_espresso'),
937 937
 
938 938
 	// Reference: packages/adapters/src/Pagination/ItemRender.tsx:9
939
-	__( 'previous', 'event_espresso' ),
939
+	__('previous', 'event_espresso'),
940 940
 
941 941
 	// Reference: packages/adapters/src/Pagination/Pagination.tsx:34
942
-	__( 'pagination', 'event_espresso' ),
942
+	__('pagination', 'event_espresso'),
943 943
 
944 944
 	// Reference: packages/adapters/src/Pagination/PerPage.tsx:36
945
-	__( 'items per page', 'event_espresso' ),
945
+	__('items per page', 'event_espresso'),
946 946
 
947 947
 	// Reference: packages/adapters/src/Pagination/constants.ts:10
948 948
 	/* translators: %s is per page value */
949
-	__( '%s / page', 'event_espresso' ),
949
+	__('%s / page', 'event_espresso'),
950 950
 
951 951
 	// Reference: packages/adapters/src/Pagination/constants.ts:13
952
-	__( 'Next Page', 'event_espresso' ),
952
+	__('Next Page', 'event_espresso'),
953 953
 
954 954
 	// Reference: packages/adapters/src/Pagination/constants.ts:14
955
-	__( 'Previous Page', 'event_espresso' ),
955
+	__('Previous Page', 'event_espresso'),
956 956
 
957 957
 	// Reference: packages/components/src/ActiveFilters/ActiveFilters.tsx:9
958
-	__( 'active filters:', 'event_espresso' ),
958
+	__('active filters:', 'event_espresso'),
959 959
 
960 960
 	// Reference: packages/components/src/ActiveFilters/FilterTag.tsx:11
961 961
 	/* translators: %s filter name */
962
-	__( 'remove filter - %s', 'event_espresso' ),
962
+	__('remove filter - %s', 'event_espresso'),
963 963
 
964 964
 	// Reference: packages/components/src/CalendarDateRange/CalendarDateRange.tsx:39
965
-	__( 'to', 'event_espresso' ),
965
+	__('to', 'event_espresso'),
966 966
 
967 967
 	// Reference: packages/components/src/CalendarDateSwitcher/CalendarDateSwitcher.tsx:33
968
-	__( 'starts', 'event_espresso' ),
968
+	__('starts', 'event_espresso'),
969 969
 
970 970
 	// Reference: packages/components/src/CalendarDateSwitcher/CalendarDateSwitcher.tsx:45
971
-	__( 'ends', 'event_espresso' ),
971
+	__('ends', 'event_espresso'),
972 972
 
973 973
 	// Reference: packages/components/src/CalendarPageDate/CalendarPageDate.tsx:57
974
-	__( 'TO', 'event_espresso' ),
974
+	__('TO', 'event_espresso'),
975 975
 
976 976
 	// Reference: packages/components/src/Confirm/ConfirmClose.tsx:8
977 977
 	// Reference: packages/components/src/Modal/ModalWithAlert.tsx:23
978
-	__( 'Are you sure you want to close this?', 'event_espresso' ),
978
+	__('Are you sure you want to close this?', 'event_espresso'),
979 979
 
980 980
 	// Reference: packages/components/src/Confirm/ConfirmDelete.tsx:8
981
-	__( 'Are you sure you want to delete this?', 'event_espresso' ),
981
+	__('Are you sure you want to delete this?', 'event_espresso'),
982 982
 
983 983
 	// Reference: packages/components/src/Confirm/useConfirmWithButton.tsx:11
984
-	__( 'Please confirm this action.', 'event_espresso' ),
984
+	__('Please confirm this action.', 'event_espresso'),
985 985
 
986 986
 	// Reference: packages/components/src/Confirm/useConfirmationDialog.tsx:35
987
-	__( 'No', 'event_espresso' ),
987
+	__('No', 'event_espresso'),
988 988
 
989 989
 	// Reference: packages/components/src/Confirm/useConfirmationDialog.tsx:36
990
-	__( 'Yes', 'event_espresso' ),
990
+	__('Yes', 'event_espresso'),
991 991
 
992 992
 	// Reference: packages/components/src/DateTimeRangePicker/index.tsx:73
993
-	__( 'save', 'event_espresso' ),
993
+	__('save', 'event_espresso'),
994 994
 
995 995
 	// Reference: packages/components/src/DebugInfo/DebugInfo.tsx:38
996
-	__( 'Hide Debug Info', 'event_espresso' ),
996
+	__('Hide Debug Info', 'event_espresso'),
997 997
 
998 998
 	// Reference: packages/components/src/DebugInfo/DebugInfo.tsx:38
999
-	__( 'Show Debug Info', 'event_espresso' ),
999
+	__('Show Debug Info', 'event_espresso'),
1000 1000
 
1001 1001
 	// Reference: packages/components/src/EditDateRangeButton/index.tsx:41
1002
-	__( 'Edit Start and End Dates and Times', 'event_espresso' ),
1002
+	__('Edit Start and End Dates and Times', 'event_espresso'),
1003 1003
 
1004 1004
 	// Reference: packages/components/src/EntityActionsMenu/entityMenuItems/Copy.tsx:9
1005
-	__( 'copy', 'event_espresso' ),
1005
+	__('copy', 'event_espresso'),
1006 1006
 
1007 1007
 	// Reference: packages/components/src/EntityActionsMenu/entityMenuItems/Edit.tsx:9
1008
-	__( 'edit', 'event_espresso' ),
1008
+	__('edit', 'event_espresso'),
1009 1009
 
1010 1010
 	// Reference: packages/components/src/EntityActionsMenu/entityMenuItems/Trash.tsx:9
1011
-	__( 'trash', 'event_espresso' ),
1011
+	__('trash', 'event_espresso'),
1012 1012
 
1013 1013
 	// Reference: packages/components/src/EntityDetailsPanel/EntityDetailsPanelSold.tsx:36
1014
-	__( 'view approved registrations for this date.', 'event_espresso' ),
1014
+	__('view approved registrations for this date.', 'event_espresso'),
1015 1015
 
1016 1016
 	// Reference: packages/components/src/EntityDetailsPanel/EntityDetailsPanelSold.tsx:37
1017
-	__( 'view approved registrations for this ticket.', 'event_espresso' ),
1017
+	__('view approved registrations for this ticket.', 'event_espresso'),
1018 1018
 
1019 1019
 	// Reference: packages/components/src/EntityList/EntityList.tsx:37
1020
-	__( 'no results found', 'event_espresso' ),
1020
+	__('no results found', 'event_espresso'),
1021 1021
 
1022 1022
 	// Reference: packages/components/src/EntityList/EntityList.tsx:38
1023
-	__( 'try changing filter settings', 'event_espresso' ),
1023
+	__('try changing filter settings', 'event_espresso'),
1024 1024
 
1025 1025
 	// Reference: packages/components/src/EntityList/filterBar/buttons/CardViewFilterButton.tsx:22
1026
-	__( 'card view', 'event_espresso' ),
1026
+	__('card view', 'event_espresso'),
1027 1027
 
1028 1028
 	// Reference: packages/components/src/EntityList/filterBar/buttons/TableViewFilterButton.tsx:22
1029
-	__( 'table view', 'event_espresso' ),
1029
+	__('table view', 'event_espresso'),
1030 1030
 
1031 1031
 	// Reference: packages/components/src/EntityList/filterBar/buttons/ToggleFiltersButton.tsx:11
1032
-	__( 'hide filters', 'event_espresso' ),
1032
+	__('hide filters', 'event_espresso'),
1033 1033
 
1034 1034
 	// Reference: packages/components/src/EntityList/filterBar/buttons/ToggleFiltersButton.tsx:11
1035
-	__( 'show filters', 'event_espresso' ),
1035
+	__('show filters', 'event_espresso'),
1036 1036
 
1037 1037
 	// Reference: packages/components/src/EntityList/filterBar/buttons/ToggleSortingButton.tsx:28
1038
-	__( 'disable sorting', 'event_espresso' ),
1038
+	__('disable sorting', 'event_espresso'),
1039 1039
 
1040 1040
 	// Reference: packages/components/src/EntityList/filterBar/buttons/ToggleSortingButton.tsx:28
1041
-	__( 'enable sorting', 'event_espresso' ),
1041
+	__('enable sorting', 'event_espresso'),
1042 1042
 
1043 1043
 	// Reference: packages/components/src/Legend/ToggleLegendButton.tsx:27
1044
-	__( 'hide legend', 'event_espresso' ),
1044
+	__('hide legend', 'event_espresso'),
1045 1045
 
1046 1046
 	// Reference: packages/components/src/Legend/ToggleLegendButton.tsx:27
1047
-	__( 'show legend', 'event_espresso' ),
1047
+	__('show legend', 'event_espresso'),
1048 1048
 
1049 1049
 	// Reference: packages/components/src/LoadingIndicator/LoadingIndicator.tsx:7
1050
-	__( 'loading …', 'event_espresso' ),
1050
+	__('loading …', 'event_espresso'),
1051 1051
 
1052 1052
 	// Reference: packages/components/src/LoadingNotice/LoadingNotice.tsx:16
1053
-	__( 'loading…', 'event_espresso' ),
1053
+	__('loading…', 'event_espresso'),
1054 1054
 
1055 1055
 	// Reference: packages/components/src/Modal/modalCloseButtonProps/index.ts:8
1056
-	__( 'close modal', 'event_espresso' ),
1056
+	__('close modal', 'event_espresso'),
1057 1057
 
1058 1058
 	// Reference: packages/components/src/PercentSign/index.tsx:11
1059
-	__( '%', 'event_espresso' ),
1059
+	__('%', 'event_espresso'),
1060 1060
 
1061 1061
 	// Reference: packages/components/src/Stepper/buttons/Next.tsx:12
1062
-	__( 'Next', 'event_espresso' ),
1062
+	__('Next', 'event_espresso'),
1063 1063
 
1064 1064
 	// Reference: packages/components/src/Stepper/buttons/Previous.tsx:12
1065
-	__( 'Previous', 'event_espresso' ),
1065
+	__('Previous', 'event_espresso'),
1066 1066
 
1067 1067
 	// Reference: packages/components/src/Steps/Steps.tsx:30
1068
-	__( 'Steps', 'event_espresso' ),
1068
+	__('Steps', 'event_espresso'),
1069 1069
 
1070 1070
 	// Reference: packages/components/src/TabbableText/index.tsx:19
1071
-	__( 'Click to edit…', 'event_espresso' ),
1071
+	__('Click to edit…', 'event_espresso'),
1072 1072
 
1073 1073
 	// Reference: packages/components/src/TimezoneTimeInfo/Content.tsx:16
1074
-	__( 'Your Local Time Zone', 'event_espresso' ),
1074
+	__('Your Local Time Zone', 'event_espresso'),
1075 1075
 
1076 1076
 	// Reference: packages/components/src/TimezoneTimeInfo/Content.tsx:21
1077
-	__( 'The Website\'s Time Zone', 'event_espresso' ),
1077
+	__('The Website\'s Time Zone', 'event_espresso'),
1078 1078
 
1079 1079
 	// Reference: packages/components/src/TimezoneTimeInfo/Content.tsx:26
1080
-	__( 'UTC (Greenwich Mean Time)', 'event_espresso' ),
1080
+	__('UTC (Greenwich Mean Time)', 'event_espresso'),
1081 1081
 
1082 1082
 	// Reference: packages/components/src/TimezoneTimeInfo/TimezoneTimeInfo.tsx:23
1083
-	__( 'This Date Converted To:', 'event_espresso' ),
1083
+	__('This Date Converted To:', 'event_espresso'),
1084 1084
 
1085 1085
 	// Reference: packages/components/src/TimezoneTimeInfo/TimezoneTimeInfo.tsx:24
1086
-	__( 'click for timezone information', 'event_espresso' ),
1086
+	__('click for timezone information', 'event_espresso'),
1087 1087
 
1088 1088
 	// Reference: packages/components/src/bulkEdit/ActionCheckbox.tsx:38
1089 1089
 	/* translators: %d entity id */
1090
-	__( 'select entity with id %d', 'event_espresso' ),
1090
+	__('select entity with id %d', 'event_espresso'),
1091 1091
 
1092 1092
 	// Reference: packages/components/src/bulkEdit/ActionCheckbox.tsx:41
1093
-	__( 'select all entities', 'event_espresso' ),
1093
+	__('select all entities', 'event_espresso'),
1094 1094
 
1095 1095
 	// Reference: packages/components/src/bulkEdit/BulkActions.tsx:52
1096
-	__( 'select all', 'event_espresso' ),
1096
+	__('select all', 'event_espresso'),
1097 1097
 
1098 1098
 	// Reference: packages/components/src/bulkEdit/BulkActions.tsx:54
1099
-	__( 'apply', 'event_espresso' ),
1099
+	__('apply', 'event_espresso'),
1100 1100
 
1101 1101
 	// Reference: packages/components/src/bulkEdit/details/BulkEditDetailsProps.tsx:20
1102
-	__( 'Note: ', 'event_espresso' ),
1102
+	__('Note: ', 'event_espresso'),
1103 1103
 
1104 1104
 	// Reference: packages/components/src/bulkEdit/details/BulkEditDetailsProps.tsx:20
1105
-	__( 'any changes will be applied to ALL of the selected entities.', 'event_espresso' ),
1105
+	__('any changes will be applied to ALL of the selected entities.', 'event_espresso'),
1106 1106
 
1107 1107
 	// Reference: packages/components/src/bulkEdit/details/BulkEditDetailsProps.tsx:26
1108
-	__( 'Bulk edit details', 'event_espresso' ),
1108
+	__('Bulk edit details', 'event_espresso'),
1109 1109
 
1110 1110
 	// Reference: packages/components/src/bulkEdit/details/Submit.tsx:28
1111
-	__( 'Are you sure you want to bulk update the details?', 'event_espresso' ),
1111
+	__('Are you sure you want to bulk update the details?', 'event_espresso'),
1112 1112
 
1113 1113
 	// Reference: packages/components/src/bulkEdit/details/Submit.tsx:29
1114
-	__( 'Bulk update details', 'event_espresso' ),
1114
+	__('Bulk update details', 'event_espresso'),
1115 1115
 
1116 1116
 	// Reference: packages/dates/src/DateRangePicker/DateRangePickerLegend.tsx:14
1117
-	__( 'day in range', 'event_espresso' ),
1117
+	__('day in range', 'event_espresso'),
1118 1118
 
1119 1119
 	// Reference: packages/dates/src/DateRangePicker/DateRangePickerLegend.tsx:18
1120 1120
 	// Reference: packages/dates/src/DateRangePicker/index.tsx:59
1121
-	__( 'end date', 'event_espresso' ),
1121
+	__('end date', 'event_espresso'),
1122 1122
 
1123 1123
 	// Reference: packages/dates/src/DateTimePicker.tsx:13
1124 1124
 	// Reference: packages/dates/src/TimePicker.tsx:14
1125
-	__( 'time', 'event_espresso' ),
1125
+	__('time', 'event_espresso'),
1126 1126
 
1127 1127
 	// Reference: packages/dates/src/constants.ts:7
1128
-	__( 'End Date & Time must be set later than the Start Date & Time', 'event_espresso' ),
1128
+	__('End Date & Time must be set later than the Start Date & Time', 'event_espresso'),
1129 1129
 
1130 1130
 	// Reference: packages/dates/src/constants.ts:9
1131
-	__( 'Start Date & Time must be set before the End Date & Time', 'event_espresso' ),
1131
+	__('Start Date & Time must be set before the End Date & Time', 'event_espresso'),
1132 1132
 
1133 1133
 	// Reference: packages/dates/src/utils/misc.ts:13
1134
-	__( 'month(s)', 'event_espresso' ),
1134
+	__('month(s)', 'event_espresso'),
1135 1135
 
1136 1136
 	// Reference: packages/dates/src/utils/misc.ts:14
1137
-	__( 'week(s)', 'event_espresso' ),
1137
+	__('week(s)', 'event_espresso'),
1138 1138
 
1139 1139
 	// Reference: packages/dates/src/utils/misc.ts:15
1140
-	__( 'day(s)', 'event_espresso' ),
1140
+	__('day(s)', 'event_espresso'),
1141 1141
 
1142 1142
 	// Reference: packages/dates/src/utils/misc.ts:16
1143
-	__( 'hour(s)', 'event_espresso' ),
1143
+	__('hour(s)', 'event_espresso'),
1144 1144
 
1145 1145
 	// Reference: packages/dates/src/utils/misc.ts:17
1146
-	__( 'minute(s)', 'event_espresso' ),
1146
+	__('minute(s)', 'event_espresso'),
1147 1147
 
1148 1148
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:104
1149
-	__( 'price types initialized', 'event_espresso' ),
1149
+	__('price types initialized', 'event_espresso'),
1150 1150
 
1151 1151
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:114
1152
-	__( 'datetimes initialized', 'event_espresso' ),
1152
+	__('datetimes initialized', 'event_espresso'),
1153 1153
 
1154 1154
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:124
1155
-	__( 'tickets initialized', 'event_espresso' ),
1155
+	__('tickets initialized', 'event_espresso'),
1156 1156
 
1157 1157
 	// Reference: packages/edtr-services/src/apollo/initialization/useCacheRehydration.ts:134
1158
-	__( 'prices initialized', 'event_espresso' ),
1158
+	__('prices initialized', 'event_espresso'),
1159 1159
 
1160 1160
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:12
1161
-	__( 'Start Date is required', 'event_espresso' ),
1161
+	__('Start Date is required', 'event_espresso'),
1162 1162
 
1163 1163
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:16
1164
-	__( 'End Date is required', 'event_espresso' ),
1164
+	__('End Date is required', 'event_espresso'),
1165 1165
 
1166 1166
 	// Reference: packages/edtr-services/src/utils/dateAndTime.ts:7
1167
-	__( 'Required', 'event_espresso' ),
1167
+	__('Required', 'event_espresso'),
1168 1168
 
1169 1169
 	// Reference: packages/form/src/renderers/RepeatableRenderer.tsx:35
1170 1170
 	/* translators: %d the entry number */
1171
-	__( 'Entry %d', 'event_espresso' ),
1171
+	__('Entry %d', 'event_espresso'),
1172 1172
 
1173 1173
 	// Reference: packages/form/src/renderers/RepeatableRenderer.tsx:51
1174
-	__( 'Add', 'event_espresso' ),
1174
+	__('Add', 'event_espresso'),
1175 1175
 
1176 1176
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:11
1177 1177
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:17
1178
-	__( 'sold out', 'event_espresso' ),
1178
+	__('sold out', 'event_espresso'),
1179 1179
 
1180 1180
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:14
1181 1181
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:14
1182
-	__( 'expired', 'event_espresso' ),
1182
+	__('expired', 'event_espresso'),
1183 1183
 
1184 1184
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:17
1185
-	__( 'upcoming', 'event_espresso' ),
1185
+	__('upcoming', 'event_espresso'),
1186 1186
 
1187 1187
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:20
1188
-	__( 'active', 'event_espresso' ),
1188
+	__('active', 'event_espresso'),
1189 1189
 
1190 1190
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:23
1191 1191
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:11
1192
-	__( 'trashed', 'event_espresso' ),
1192
+	__('trashed', 'event_espresso'),
1193 1193
 
1194 1194
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:26
1195
-	__( 'cancelled', 'event_espresso' ),
1195
+	__('cancelled', 'event_espresso'),
1196 1196
 
1197 1197
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:29
1198
-	__( 'postponed', 'event_espresso' ),
1198
+	__('postponed', 'event_espresso'),
1199 1199
 
1200 1200
 	// Reference: packages/helpers/src/datetimes/getStatusTextLabel.ts:33
1201
-	__( 'inactive', 'event_espresso' ),
1201
+	__('inactive', 'event_espresso'),
1202 1202
 
1203 1203
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:20
1204
-	__( 'pending', 'event_espresso' ),
1204
+	__('pending', 'event_espresso'),
1205 1205
 
1206 1206
 	// Reference: packages/helpers/src/tickets/getStatusTextLabel.ts:23
1207
-	__( 'on sale', 'event_espresso' ),
1207
+	__('on sale', 'event_espresso'),
1208 1208
 
1209 1209
 	// Reference: packages/predicates/src/registration/statusOptions.ts:14
1210
-	__( 'Declined', 'event_espresso' ),
1210
+	__('Declined', 'event_espresso'),
1211 1211
 
1212 1212
 	// Reference: packages/predicates/src/registration/statusOptions.ts:18
1213
-	__( 'Incomplete', 'event_espresso' ),
1213
+	__('Incomplete', 'event_espresso'),
1214 1214
 
1215 1215
 	// Reference: packages/predicates/src/registration/statusOptions.ts:22
1216
-	__( 'Not Approved', 'event_espresso' ),
1216
+	__('Not Approved', 'event_espresso'),
1217 1217
 
1218 1218
 	// Reference: packages/predicates/src/registration/statusOptions.ts:26
1219
-	__( 'Pending Payment', 'event_espresso' ),
1219
+	__('Pending Payment', 'event_espresso'),
1220 1220
 
1221 1221
 	// Reference: packages/predicates/src/registration/statusOptions.ts:30
1222
-	__( 'Wait List', 'event_espresso' ),
1222
+	__('Wait List', 'event_espresso'),
1223 1223
 
1224 1224
 	// Reference: packages/predicates/src/registration/statusOptions.ts:6
1225
-	__( 'Approved', 'event_espresso' ),
1225
+	__('Approved', 'event_espresso'),
1226 1226
 
1227 1227
 	// Reference: packages/rich-text-editor/src/components/ToolbarControls/HeadingControls.tsx:23
1228
-	__( 'heading selector', 'event_espresso' ),
1228
+	__('heading selector', 'event_espresso'),
1229 1229
 
1230 1230
 	// Reference: packages/rich-text-editor/src/components/constants.ts:12
1231
-	__( 'blockquote', 'event_espresso' ),
1231
+	__('blockquote', 'event_espresso'),
1232 1232
 
1233 1233
 	// Reference: packages/rich-text-editor/src/components/constants.ts:13
1234
-	__( 'unordered list', 'event_espresso' ),
1234
+	__('unordered list', 'event_espresso'),
1235 1235
 
1236 1236
 	// Reference: packages/rich-text-editor/src/components/constants.ts:14
1237
-	__( 'ordered list', 'event_espresso' ),
1237
+	__('ordered list', 'event_espresso'),
1238 1238
 
1239 1239
 	// Reference: packages/rich-text-editor/src/components/constants.ts:27
1240
-	__( 'bold', 'event_espresso' ),
1240
+	__('bold', 'event_espresso'),
1241 1241
 
1242 1242
 	// Reference: packages/rich-text-editor/src/components/constants.ts:28
1243
-	__( 'italic', 'event_espresso' ),
1243
+	__('italic', 'event_espresso'),
1244 1244
 
1245 1245
 	// Reference: packages/rich-text-editor/src/components/constants.ts:29
1246
-	__( 'underline', 'event_espresso' ),
1246
+	__('underline', 'event_espresso'),
1247 1247
 
1248 1248
 	// Reference: packages/tpc/src/buttons/AddPriceModifierButton.tsx:15
1249
-	__( 'add new price modifier after this row', 'event_espresso' ),
1249
+	__('add new price modifier after this row', 'event_espresso'),
1250 1250
 
1251 1251
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:13
1252
-	__( 'Delete all prices', 'event_espresso' ),
1252
+	__('Delete all prices', 'event_espresso'),
1253 1253
 
1254 1254
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:26
1255
-	__( 'Are you sure you want to delete all of this ticket\'s prices and make it free? This action is permanent and can not be undone.', 'event_espresso' ),
1255
+	__('Are you sure you want to delete all of this ticket\'s prices and make it free? This action is permanent and can not be undone.', 'event_espresso'),
1256 1256
 
1257 1257
 	// Reference: packages/tpc/src/buttons/DeleteAllPricesButton.tsx:30
1258
-	__( 'Delete all prices?', 'event_espresso' ),
1258
+	__('Delete all prices?', 'event_espresso'),
1259 1259
 
1260 1260
 	// Reference: packages/tpc/src/buttons/DeletePriceModifierButton.tsx:12
1261
-	__( 'delete price modifier', 'event_espresso' ),
1261
+	__('delete price modifier', 'event_espresso'),
1262 1262
 
1263 1263
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:15
1264
-	__( 'Ticket base price is being reverse calculated from bottom to top starting with the ticket total. Entering a new ticket total will reverse calculate the ticket base price after applying all price modifiers in reverse. Click to turn off reverse calculations', 'event_espresso' ),
1264
+	__('Ticket base price is being reverse calculated from bottom to top starting with the ticket total. Entering a new ticket total will reverse calculate the ticket base price after applying all price modifiers in reverse. Click to turn off reverse calculations', 'event_espresso'),
1265 1265
 
1266 1266
 	// Reference: packages/tpc/src/buttons/ReverseCalculateButton.tsx:18
1267
-	__( 'Ticket total is being calculated normally from top to bottom starting from the base price. Entering a new ticket base price will recalculate the ticket total after applying all price modifiers. Click to turn on reverse calculations', 'event_espresso' ),
1267
+	__('Ticket total is being calculated normally from top to bottom starting from the base price. Entering a new ticket base price will recalculate the ticket total after applying all price modifiers. Click to turn on reverse calculations', 'event_espresso'),
1268 1268
 
1269 1269
 	// Reference: packages/tpc/src/buttons/TicketPriceCalculatorButton.tsx:29
1270
-	__( 'ticket price calculator', 'event_espresso' ),
1270
+	__('ticket price calculator', 'event_espresso'),
1271 1271
 
1272 1272
 	// Reference: packages/tpc/src/buttons/taxes/AddDefaultTaxesButton.tsx:10
1273
-	__( 'Add default taxes', 'event_espresso' ),
1273
+	__('Add default taxes', 'event_espresso'),
1274 1274
 
1275 1275
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:11
1276
-	__( 'Are you sure you want to remove all of this ticket\'s taxes?', 'event_espresso' ),
1276
+	__('Are you sure you want to remove all of this ticket\'s taxes?', 'event_espresso'),
1277 1277
 
1278 1278
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:15
1279
-	__( 'Remove all taxes?', 'event_espresso' ),
1279
+	__('Remove all taxes?', 'event_espresso'),
1280 1280
 
1281 1281
 	// Reference: packages/tpc/src/buttons/taxes/RemoveTaxesButton.tsx:8
1282
-	__( 'Remove taxes', 'event_espresso' ),
1282
+	__('Remove taxes', 'event_espresso'),
1283 1283
 
1284 1284
 	// Reference: packages/tpc/src/components/DefaultPricesInfo.tsx:28
1285
-	__( 'Modify default prices.', 'event_espresso' ),
1285
+	__('Modify default prices.', 'event_espresso'),
1286 1286
 
1287 1287
 	// Reference: packages/tpc/src/components/DefaultTaxesInfo.tsx:28
1288
-	__( 'New default taxes are available. Click the - Add default taxes - button to add them now.', 'event_espresso' ),
1288
+	__('New default taxes are available. Click the - Add default taxes - button to add them now.', 'event_espresso'),
1289 1289
 
1290 1290
 	// Reference: packages/tpc/src/components/NoPricesBanner/AddDefaultPricesButton.tsx:10
1291
-	__( 'Add default prices', 'event_espresso' ),
1291
+	__('Add default prices', 'event_espresso'),
1292 1292
 
1293 1293
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:14
1294
-	__( 'This Ticket is Currently Free', 'event_espresso' ),
1294
+	__('This Ticket is Currently Free', 'event_espresso'),
1295 1295
 
1296 1296
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:22
1297 1297
 	/* translators: %s default prices */
1298
-	__( 'Click the button below to load your %s into the calculator.', 'event_espresso' ),
1298
+	__('Click the button below to load your %s into the calculator.', 'event_espresso'),
1299 1299
 
1300 1300
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:23
1301
-	__( 'default prices', 'event_espresso' ),
1301
+	__('default prices', 'event_espresso'),
1302 1302
 
1303 1303
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:30
1304
-	__( 'Additional ticket price modifiers can be added or removed.', 'event_espresso' ),
1304
+	__('Additional ticket price modifiers can be added or removed.', 'event_espresso'),
1305 1305
 
1306 1306
 	// Reference: packages/tpc/src/components/NoPricesBanner/index.tsx:33
1307
-	__( 'Click the save button below to assign which dates this ticket will be available for purchase on.', 'event_espresso' ),
1307
+	__('Click the save button below to assign which dates this ticket will be available for purchase on.', 'event_espresso'),
1308 1308
 
1309 1309
 	// Reference: packages/tpc/src/components/TicketPriceCalculatorModal.tsx:32
1310 1310
 	/* translators: %s ticket name */
1311
-	__( 'Price Calculator for Ticket: %s', 'event_espresso' ),
1311
+	__('Price Calculator for Ticket: %s', 'event_espresso'),
1312 1312
 
1313 1313
 	// Reference: packages/tpc/src/components/table/Table.tsx:43
1314
-	__( 'Ticket Price Calculator', 'event_espresso' ),
1314
+	__('Ticket Price Calculator', 'event_espresso'),
1315 1315
 
1316 1316
 	// Reference: packages/tpc/src/components/table/useFooterRowGenerator.tsx:41
1317
-	__( 'Total', 'event_espresso' ),
1317
+	__('Total', 'event_espresso'),
1318 1318
 
1319 1319
 	// Reference: packages/tpc/src/components/table/useFooterRowGenerator.tsx:50
1320
-	__( 'ticket total', 'event_espresso' ),
1320
+	__('ticket total', 'event_espresso'),
1321 1321
 
1322 1322
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:29
1323
-	__( 'Price Type', 'event_espresso' ),
1323
+	__('Price Type', 'event_espresso'),
1324 1324
 
1325 1325
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:35
1326
-	__( 'Label', 'event_espresso' ),
1326
+	__('Label', 'event_espresso'),
1327 1327
 
1328 1328
 	// Reference: packages/tpc/src/components/table/useHeaderRowGenerator.ts:47
1329
-	__( 'Amount', 'event_espresso' ),
1329
+	__('Amount', 'event_espresso'),
1330 1330
 
1331 1331
 	// Reference: packages/tpc/src/inputs/PriceAmountInput.tsx:34
1332
-	__( 'amount', 'event_espresso' ),
1332
+	__('amount', 'event_espresso'),
1333 1333
 
1334 1334
 	// Reference: packages/tpc/src/inputs/PriceAmountInput.tsx:45
1335
-	__( 'amount…', 'event_espresso' ),
1335
+	__('amount…', 'event_espresso'),
1336 1336
 
1337 1337
 	// Reference: packages/tpc/src/inputs/PriceDescriptionInput.tsx:10
1338
-	__( 'price description', 'event_espresso' ),
1338
+	__('price description', 'event_espresso'),
1339 1339
 
1340 1340
 	// Reference: packages/tpc/src/inputs/PriceDescriptionInput.tsx:15
1341
-	__( 'description…', 'event_espresso' ),
1341
+	__('description…', 'event_espresso'),
1342 1342
 
1343 1343
 	// Reference: packages/tpc/src/inputs/PriceIdInput.tsx:9
1344
-	__( 'price id', 'event_espresso' ),
1344
+	__('price id', 'event_espresso'),
1345 1345
 
1346 1346
 	// Reference: packages/tpc/src/inputs/PriceNameInput.tsx:10
1347
-	__( 'price name', 'event_espresso' ),
1347
+	__('price name', 'event_espresso'),
1348 1348
 
1349 1349
 	// Reference: packages/tpc/src/inputs/PriceNameInput.tsx:15
1350
-	__( 'label…', 'event_espresso' ),
1350
+	__('label…', 'event_espresso'),
1351 1351
 
1352 1352
 	// Reference: packages/tpc/src/inputs/PriceTypeInput.tsx:16
1353
-	__( 'price type', 'event_espresso' ),
1353
+	__('price type', 'event_espresso'),
1354 1354
 
1355 1355
 	// Reference: packages/tpc/src/utils/constants.ts:13
1356
-	__( 'Ticket price modifications are blocked for Tickets that have already been sold to registrants, because doing so would negatively affect internal accounting for the event. If you still need to modify ticket prices, then create a copy of those tickets, edit the prices for the new tickets, and then archive the old tickets.', 'event_espresso' )
1356
+	__('Ticket price modifications are blocked for Tickets that have already been sold to registrants, because doing so would negatively affect internal accounting for the event. If you still need to modify ticket prices, then create a copy of those tickets, edit the prices for the new tickets, and then archive the old tickets.', 'event_espresso')
1357 1357
 );
1358 1358
 /* THIS IS THE END OF THE GENERATED FILE */
Please login to merge, or discard this patch.