Completed
Branch legacy-meta-boxes (825bff)
by
unknown
17:12 queued 08:21
created
admin_pages/events/Events_Admin_Page.core.php 2 patches
Indentation   +2860 added lines, -2860 removed lines patch added patch discarded remove patch
@@ -15,2864 +15,2864 @@
 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
-            array(),
566
-            EVENT_ESPRESSO_VERSION
567
-        );
568
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
569
-        wp_enqueue_style('events-admin-css');
570
-        wp_enqueue_style('ee-cat-admin');
571
-        // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
572
-        // registers for all views
573
-        // scripts
574
-        wp_register_script(
575
-            'event_editor_js',
576
-            EVENTS_ASSETS_URL . 'event_editor.js',
577
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
578
-            EVENT_ESPRESSO_VERSION,
579
-            true
580
-        );
581
-    }
582
-
583
-
584
-    /**
585
-     * Enqueuing scripts and styles specific to this view
586
-     */
587
-    public function load_scripts_styles_create_new()
588
-    {
589
-        $this->load_scripts_styles_edit();
590
-    }
591
-
592
-
593
-    /**
594
-     * Enqueuing scripts and styles specific to this view
595
-     */
596
-    public function load_scripts_styles_edit()
597
-    {
598
-        // styles
599
-        wp_enqueue_style('espresso-ui-theme');
600
-        wp_register_style(
601
-            'event-editor-css',
602
-            EVENTS_ASSETS_URL . 'event-editor.css',
603
-            array('ee-admin-css'),
604
-            EVENT_ESPRESSO_VERSION
605
-        );
606
-        wp_enqueue_style('event-editor-css');
607
-        // scripts
608
-        wp_register_script(
609
-            'event-datetime-metabox',
610
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
611
-            array('event_editor_js', 'ee-datepicker'),
612
-            EVENT_ESPRESSO_VERSION
613
-        );
614
-        wp_enqueue_script('event-datetime-metabox');
615
-    }
616
-
617
-
618
-    /**
619
-     * Populating the _views property for the category list table view.
620
-     */
621
-    protected function _set_list_table_views_category_list()
622
-    {
623
-        $this->_views = array(
624
-            'all' => array(
625
-                'slug'        => 'all',
626
-                'label'       => esc_html__('All', 'event_espresso'),
627
-                'count'       => 0,
628
-                'bulk_action' => array(
629
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
630
-                ),
631
-            ),
632
-        );
633
-    }
634
-
635
-
636
-    /**
637
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
638
-     */
639
-    public function admin_init()
640
-    {
641
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
642
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
643
-            'event_espresso'
644
-        );
645
-    }
646
-
647
-
648
-    /**
649
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
650
-     * group.
651
-     */
652
-    public function admin_notices()
653
-    {
654
-    }
655
-
656
-
657
-    /**
658
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
659
-     * this admin page group.
660
-     */
661
-    public function admin_footer_scripts()
662
-    {
663
-    }
664
-
665
-
666
-    /**
667
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
668
-     * warning (via EE_Error::add_error());
669
-     *
670
-     * @param  EE_Event $event Event object
671
-     * @param string    $req_type
672
-     * @return void
673
-     * @throws EE_Error
674
-     * @access public
675
-     */
676
-    public function verify_event_edit($event = null, $req_type = '')
677
-    {
678
-        // don't need to do this when processing
679
-        if (! empty($req_type)) {
680
-            return;
681
-        }
682
-        // no event?
683
-        if (! $event instanceof EE_Event) {
684
-            $event = $this->_cpt_model_obj;
685
-        }
686
-        // STILL no event?
687
-        if (! $event instanceof EE_Event) {
688
-            return;
689
-        }
690
-        $orig_status = $event->status();
691
-        // first check if event is active.
692
-        if ($orig_status === EEM_Event::cancelled
693
-            || $orig_status === EEM_Event::postponed
694
-            || $event->is_expired()
695
-            || $event->is_inactive()
696
-        ) {
697
-            return;
698
-        }
699
-        // made it here so it IS active... next check that any of the tickets are sold.
700
-        if ($event->is_sold_out(true)) {
701
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
702
-                EE_Error::add_attention(
703
-                    sprintf(
704
-                        esc_html__(
705
-                            '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.',
706
-                            'event_espresso'
707
-                        ),
708
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
709
-                    )
710
-                );
711
-            }
712
-            return;
713
-        }
714
-        if ($orig_status === EEM_Event::sold_out) {
715
-            EE_Error::add_attention(
716
-                sprintf(
717
-                    esc_html__(
718
-                        '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.',
719
-                        'event_espresso'
720
-                    ),
721
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
722
-                )
723
-            );
724
-        }
725
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
726
-        if (! $event->tickets_on_sale()) {
727
-            return;
728
-        }
729
-        // made it here so show warning
730
-        $this->_edit_event_warning();
731
-    }
732
-
733
-
734
-    /**
735
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
736
-     * When needed, hook this into a EE_Error::add_error() notice.
737
-     *
738
-     * @access protected
739
-     * @return void
740
-     */
741
-    protected function _edit_event_warning()
742
-    {
743
-        // we don't want to add warnings during these requests
744
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
745
-            return;
746
-        }
747
-        EE_Error::add_attention(
748
-            sprintf(
749
-                esc_html__(
750
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
751
-                    'event_espresso'
752
-                ),
753
-                '<a class="espresso-help-tab-lnk">',
754
-                '</a>'
755
-            )
756
-        );
757
-    }
758
-
759
-
760
-    /**
761
-     * When a user is creating a new event, notify them if they haven't set their timezone.
762
-     * Otherwise, do the normal logic
763
-     *
764
-     * @return string
765
-     * @throws EE_Error
766
-     * @throws InvalidArgumentException
767
-     * @throws InvalidDataTypeException
768
-     * @throws InvalidInterfaceException
769
-     */
770
-    protected function _create_new_cpt_item()
771
-    {
772
-        $has_timezone_string = get_option('timezone_string');
773
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
774
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
775
-            EE_Error::add_attention(
776
-                sprintf(
777
-                    __(
778
-                        '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',
779
-                        'event_espresso'
780
-                    ),
781
-                    '<br>',
782
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
783
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
784
-                    . '</select>',
785
-                    '<button class="button button-secondary timezone-submit">',
786
-                    '</button><span class="spinner"></span>'
787
-                ),
788
-                __FILE__,
789
-                __FUNCTION__,
790
-                __LINE__
791
-            );
792
-        }
793
-        parent::_create_new_cpt_item();
794
-    }
795
-
796
-
797
-    /**
798
-     * Sets the _views property for the default route in this admin page group.
799
-     */
800
-    protected function _set_list_table_views_default()
801
-    {
802
-        $this->_views = array(
803
-            'all'   => array(
804
-                'slug'        => 'all',
805
-                'label'       => esc_html__('View All Events', 'event_espresso'),
806
-                'count'       => 0,
807
-                'bulk_action' => array(
808
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
809
-                ),
810
-            ),
811
-            'draft' => array(
812
-                'slug'        => 'draft',
813
-                'label'       => esc_html__('Draft', 'event_espresso'),
814
-                'count'       => 0,
815
-                'bulk_action' => array(
816
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
817
-                ),
818
-            ),
819
-        );
820
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
821
-            $this->_views['trash'] = array(
822
-                'slug'        => 'trash',
823
-                'label'       => esc_html__('Trash', 'event_espresso'),
824
-                'count'       => 0,
825
-                'bulk_action' => array(
826
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
827
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
828
-                ),
829
-            );
830
-        }
831
-    }
832
-
833
-
834
-    /**
835
-     * Provides the legend item array for the default list table view.
836
-     *
837
-     * @return array
838
-     */
839
-    protected function _event_legend_items()
840
-    {
841
-        $items = array(
842
-            'view_details'   => array(
843
-                'class' => 'dashicons dashicons-search',
844
-                'desc'  => esc_html__('View Event', 'event_espresso'),
845
-            ),
846
-            'edit_event'     => array(
847
-                'class' => 'ee-icon ee-icon-calendar-edit',
848
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
849
-            ),
850
-            'view_attendees' => array(
851
-                'class' => 'dashicons dashicons-groups',
852
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
853
-            ),
854
-        );
855
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
856
-        $statuses = array(
857
-            'sold_out_status'  => array(
858
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
859
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
860
-            ),
861
-            'active_status'    => array(
862
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
863
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
864
-            ),
865
-            'upcoming_status'  => array(
866
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
867
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
868
-            ),
869
-            'postponed_status' => array(
870
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
871
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
872
-            ),
873
-            'cancelled_status' => array(
874
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
875
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
876
-            ),
877
-            'expired_status'   => array(
878
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
879
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
880
-            ),
881
-            'inactive_status'  => array(
882
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
883
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
884
-            ),
885
-        );
886
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
887
-        return array_merge($items, $statuses);
888
-    }
889
-
890
-
891
-    /**
892
-     * @return EEM_Event
893
-     * @throws EE_Error
894
-     * @throws InvalidArgumentException
895
-     * @throws InvalidDataTypeException
896
-     * @throws InvalidInterfaceException
897
-     * @throws ReflectionException
898
-     */
899
-    private function _event_model()
900
-    {
901
-        if (! $this->_event_model instanceof EEM_Event) {
902
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
903
-        }
904
-        return $this->_event_model;
905
-    }
906
-
907
-
908
-    /**
909
-     * Adds extra buttons to the WP CPT permalink field row.
910
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
911
-     *
912
-     * @param  string $return    the current html
913
-     * @param  int    $id        the post id for the page
914
-     * @param  string $new_title What the title is
915
-     * @param  string $new_slug  what the slug is
916
-     * @return string            The new html string for the permalink area
917
-     */
918
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
919
-    {
920
-        // make sure this is only when editing
921
-        if (! empty($id)) {
922
-            $post = get_post($id);
923
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
924
-                       . esc_html__('Shortcode', 'event_espresso')
925
-                       . '</a> ';
926
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
927
-                       . $post->ID
928
-                       . ']">';
929
-        }
930
-        return $return;
931
-    }
932
-
933
-
934
-    /**
935
-     * _events_overview_list_table
936
-     * This contains the logic for showing the events_overview list
937
-     *
938
-     * @access protected
939
-     * @return void
940
-     * @throws DomainException
941
-     * @throws EE_Error
942
-     * @throws InvalidArgumentException
943
-     * @throws InvalidDataTypeException
944
-     * @throws InvalidInterfaceException
945
-     */
946
-    protected function _events_overview_list_table()
947
-    {
948
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
949
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
950
-            ? (array) $this->_template_args['after_list_table']
951
-            : array();
952
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
953
-                . EEH_Template::get_button_or_link(
954
-                    get_post_type_archive_link('espresso_events'),
955
-                    esc_html__('View Event Archive Page', 'event_espresso'),
956
-                    'button'
957
-                );
958
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
959
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
960
-            'create_new',
961
-            'add',
962
-            array(),
963
-            'add-new-h2'
964
-        );
965
-        $this->display_admin_list_table_page_with_no_sidebar();
966
-    }
967
-
968
-
969
-    /**
970
-     * this allows for extra misc actions in the default WP publish box
971
-     *
972
-     * @return void
973
-     * @throws DomainException
974
-     * @throws EE_Error
975
-     * @throws InvalidArgumentException
976
-     * @throws InvalidDataTypeException
977
-     * @throws InvalidInterfaceException
978
-     * @throws ReflectionException
979
-     */
980
-    public function extra_misc_actions_publish_box()
981
-    {
982
-        $this->_generate_publish_box_extra_content();
983
-    }
984
-
985
-
986
-    /**
987
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
988
-     * saved.
989
-     * Typically you would use this to save any additional data.
990
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
991
-     * ALSO very important.  When a post transitions from scheduled to published,
992
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
993
-     * other meta saves. So MAKE sure that you handle this accordingly.
994
-     *
995
-     * @access protected
996
-     * @abstract
997
-     * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
998
-     * @param object $post    The post object of the cpt that was saved.
999
-     * @return void
1000
-     * @throws EE_Error
1001
-     * @throws InvalidArgumentException
1002
-     * @throws InvalidDataTypeException
1003
-     * @throws InvalidInterfaceException
1004
-     * @throws ReflectionException
1005
-     */
1006
-    protected function _insert_update_cpt_item($post_id, $post)
1007
-    {
1008
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1009
-            // get out we're not processing an event save.
1010
-            return;
1011
-        }
1012
-        $event_values = array(
1013
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1014
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1015
-            'EVT_additional_limit'            => min(
1016
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1017
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1018
-            ),
1019
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1020
-                ? $this->_req_data['EVT_default_registration_status']
1021
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
1022
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1023
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1024
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1025
-                ? $this->_req_data['timezone_string'] : null,
1026
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1027
-                ? $this->_req_data['externalURL'] : null,
1028
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1029
-                ? $this->_req_data['event_phone'] : null,
1030
-        );
1031
-        // update event
1032
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1033
-        // 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!
1034
-        $get_one_where = array(
1035
-            $this->_event_model()->primary_key_name() => $post_id,
1036
-            'OR'                                      => array(
1037
-                'status'   => $post->post_status,
1038
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1039
-                // but the returned object here has a status of "publish", so use the original post status as well
1040
-                'status*1' => $this->_req_data['original_post_status'],
1041
-            ),
1042
-        );
1043
-        $event = $this->_event_model()->get_one(array($get_one_where));
1044
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1045
-        $event_update_callbacks = apply_filters(
1046
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1047
-            array(
1048
-                array($this, '_default_venue_update'),
1049
-                array($this, '_default_tickets_update'),
1050
-            )
1051
-        );
1052
-        $att_success = true;
1053
-        foreach ($event_update_callbacks as $e_callback) {
1054
-            $_success = is_callable($e_callback)
1055
-                ? $e_callback($event, $this->_req_data)
1056
-                : false;
1057
-            // if ANY of these updates fail then we want the appropriate global error message
1058
-            $att_success = ! $att_success ? $att_success : $_success;
1059
-        }
1060
-        // any errors?
1061
-        if ($success && false === $att_success) {
1062
-            EE_Error::add_error(
1063
-                esc_html__(
1064
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1065
-                    'event_espresso'
1066
-                ),
1067
-                __FILE__,
1068
-                __FUNCTION__,
1069
-                __LINE__
1070
-            );
1071
-        } elseif ($success === false) {
1072
-            EE_Error::add_error(
1073
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1074
-                __FILE__,
1075
-                __FUNCTION__,
1076
-                __LINE__
1077
-            );
1078
-        }
1079
-    }
1080
-
1081
-
1082
-    /**
1083
-     * @param int $post_id
1084
-     * @param int $revision_id
1085
-     * @throws EE_Error
1086
-     * @throws InvalidArgumentException
1087
-     * @throws InvalidDataTypeException
1088
-     * @throws InvalidInterfaceException
1089
-     * @throws ReflectionException
1090
-     * @see parent::restore_item()
1091
-     */
1092
-    protected function _restore_cpt_item($post_id, $revision_id)
1093
-    {
1094
-        // copy existing event meta to new post
1095
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1096
-        if ($post_evt instanceof EE_Event) {
1097
-            // meta revision restore
1098
-            $post_evt->restore_revision($revision_id);
1099
-            // related objs restore
1100
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1101
-        }
1102
-    }
1103
-
1104
-
1105
-    /**
1106
-     * Attach the venue to the Event
1107
-     *
1108
-     * @param EE_Event $evtobj Event Object to add the venue to
1109
-     * @param array    $data   The request data from the form
1110
-     * @return bool           Success or fail.
1111
-     * @throws EE_Error
1112
-     * @throws InvalidArgumentException
1113
-     * @throws InvalidDataTypeException
1114
-     * @throws InvalidInterfaceException
1115
-     * @throws ReflectionException
1116
-     */
1117
-    protected function _default_venue_update(EE_Event $evtobj, $data)
1118
-    {
1119
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1120
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1121
-        $rows_affected = null;
1122
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1123
-        // very important.  If we don't have a venue name...
1124
-        // then we'll get out because not necessary to create empty venue
1125
-        if (empty($data['venue_title'])) {
1126
-            return false;
1127
-        }
1128
-        $venue_array = array(
1129
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1130
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1131
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1132
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1133
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1134
-                : null,
1135
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1136
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1137
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1138
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1139
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1140
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1141
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1142
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1143
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1144
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1145
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1146
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1147
-            'status'              => 'publish',
1148
-        );
1149
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1150
-        if (! empty($venue_id)) {
1151
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1152
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1153
-            // 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.
1154
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1155
-            return $rows_affected > 0;
1156
-        }
1157
-        // we insert the venue
1158
-        $venue_id = $venue_model->insert($venue_array);
1159
-        $evtobj->_add_relation_to($venue_id, 'Venue');
1160
-        return ! empty($venue_id) ? true : false;
1161
-        // when we have the ancestor come in it's already been handled by the revision save.
1162
-    }
1163
-
1164
-
1165
-    /**
1166
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1167
-     *
1168
-     * @param EE_Event $evtobj The Event object we're attaching data to
1169
-     * @param array    $data   The request data from the form
1170
-     * @return array
1171
-     * @throws EE_Error
1172
-     * @throws InvalidArgumentException
1173
-     * @throws InvalidDataTypeException
1174
-     * @throws InvalidInterfaceException
1175
-     * @throws ReflectionException
1176
-     * @throws Exception
1177
-     */
1178
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1179
-    {
1180
-        if (EE_Registry::instance()->CFG->admin->useAdvancedEditor()) {
1181
-            return [];
1182
-        }
1183
-        $success = true;
1184
-        $saved_dtt = null;
1185
-        $saved_tickets = array();
1186
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1187
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1188
-            // trim all values to ensure any excess whitespace is removed.
1189
-            $dtt = array_map('trim', $dtt);
1190
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1191
-                : $dtt['DTT_EVT_start'];
1192
-            $datetime_values = array(
1193
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1194
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1195
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1196
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1197
-                'DTT_order'     => $row,
1198
-            );
1199
-            // 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.
1200
-            if (! empty($dtt['DTT_ID'])) {
1201
-                $DTM = EE_Registry::instance()
1202
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1203
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1204
-                $DTM->set_date_format($incoming_date_formats[0]);
1205
-                $DTM->set_time_format($incoming_date_formats[1]);
1206
-                foreach ($datetime_values as $field => $value) {
1207
-                    $DTM->set($field, $value);
1208
-                }
1209
-                // 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.
1210
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1211
-            } else {
1212
-                $DTM = EE_Registry::instance()->load_class(
1213
-                    'Datetime',
1214
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1215
-                    false,
1216
-                    false
1217
-                );
1218
-                foreach ($datetime_values as $field => $value) {
1219
-                    $DTM->set($field, $value);
1220
-                }
1221
-            }
1222
-            $DTM->save();
1223
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1224
-            // load DTT helper
1225
-            // 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.
1226
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1227
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1228
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1229
-                $DTT->save();
1230
-            }
1231
-            // 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.
1232
-            $saved_dtt = $DTT;
1233
-            $success = ! $success ? $success : $DTT;
1234
-            // if ANY of these updates fail then we want the appropriate global error message.
1235
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1236
-        }
1237
-        // no dtts get deleted so we don't do any of that logic here.
1238
-        // update tickets next
1239
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1240
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1241
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1242
-            $update_prices = false;
1243
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1244
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1245
-            // trim inputs to ensure any excess whitespace is removed.
1246
-            $tkt = array_map('trim', $tkt);
1247
-            if (empty($tkt['TKT_start_date'])) {
1248
-                // let's use now in the set timezone.
1249
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1250
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1251
-            }
1252
-            if (empty($tkt['TKT_end_date'])) {
1253
-                // use the start date of the first datetime
1254
-                $dtt = $evtobj->first_datetime();
1255
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1256
-                    $incoming_date_formats[0],
1257
-                    $incoming_date_formats[1]
1258
-                );
1259
-            }
1260
-            $TKT_values = array(
1261
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1262
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1263
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1264
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1265
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1266
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1267
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1268
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1269
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1270
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1271
-                'TKT_row'         => $row,
1272
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1273
-                'TKT_price'       => $ticket_price,
1274
-            );
1275
-            // 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.
1276
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1277
-                $TKT_values['TKT_ID'] = 0;
1278
-                $TKT_values['TKT_is_default'] = 0;
1279
-                $TKT_values['TKT_price'] = $ticket_price;
1280
-                $update_prices = true;
1281
-            }
1282
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1283
-            // 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.
1284
-            // 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.
1285
-            if (! empty($tkt['TKT_ID'])) {
1286
-                $TKT = EE_Registry::instance()
1287
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1288
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1289
-                if ($TKT instanceof EE_Ticket) {
1290
-                    $ticket_sold = $TKT->count_related(
1291
-                        'Registration',
1292
-                        array(
1293
-                            array(
1294
-                                'STS_ID' => array(
1295
-                                    'NOT IN',
1296
-                                    array(EEM_Registration::status_id_incomplete),
1297
-                                ),
1298
-                            ),
1299
-                        )
1300
-                    ) > 0;
1301
-                    // let's just check the total price for the existing ticket and determine if it matches the new
1302
-                    // total price.  if they are different then we create a new ticket (if tickets sold)
1303
-                    // if they aren't different then we go ahead and modify existing ticket.
1304
-                    $create_new_TKT = $ticket_sold && ! $TKT->deleted() && EEH_Money::compare_floats(
1305
-                        $ticket_price,
1306
-                        $TKT->get('TKT_price'),
1307
-                        '!=='
1308
-                    );
1309
-                    $TKT->set_date_format($incoming_date_formats[0]);
1310
-                    $TKT->set_time_format($incoming_date_formats[1]);
1311
-                    // set new values
1312
-                    foreach ($TKT_values as $field => $value) {
1313
-                        if ($field === 'TKT_qty') {
1314
-                            $TKT->set_qty($value);
1315
-                        } else {
1316
-                            $TKT->set($field, $value);
1317
-                        }
1318
-                    }
1319
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1320
-                    if ($create_new_TKT) {
1321
-                        // archive the old ticket first
1322
-                        $TKT->set('TKT_deleted', 1);
1323
-                        $TKT->save();
1324
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1325
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1326
-                        // 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.
1327
-                        $TKT = clone $TKT;
1328
-                        $TKT->set('TKT_ID', 0);
1329
-                        $TKT->set('TKT_deleted', 0);
1330
-                        $TKT->set('TKT_price', $ticket_price);
1331
-                        $TKT->set('TKT_sold', 0);
1332
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1333
-                        $update_prices = true;
1334
-                    }
1335
-                    // make sure price is set if it hasn't been already
1336
-                    $TKT->set('TKT_price', $ticket_price);
1337
-                }
1338
-            } else {
1339
-                // no TKT_id so a new TKT
1340
-                $TKT_values['TKT_price'] = $ticket_price;
1341
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1342
-                if ($TKT instanceof EE_Ticket) {
1343
-                    // need to reset values to properly account for the date formats
1344
-                    $TKT->set_date_format($incoming_date_formats[0]);
1345
-                    $TKT->set_time_format($incoming_date_formats[1]);
1346
-                    $TKT->set_timezone($evtobj->get_timezone());
1347
-                    // set new values
1348
-                    foreach ($TKT_values as $field => $value) {
1349
-                        if ($field === 'TKT_qty') {
1350
-                            $TKT->set_qty($value);
1351
-                        } else {
1352
-                            $TKT->set($field, $value);
1353
-                        }
1354
-                    }
1355
-                    $update_prices = true;
1356
-                }
1357
-            }
1358
-            // cap ticket qty by datetime reg limits
1359
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1360
-            // update ticket.
1361
-            $TKT->save();
1362
-            // 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.
1363
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1364
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1365
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1366
-                $TKT->save();
1367
-            }
1368
-            // initially let's add the ticket to the dtt
1369
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1370
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1371
-            // add prices to ticket
1372
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1373
-        }
1374
-        // 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.
1375
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
1376
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1377
-        foreach ($tickets_removed as $id) {
1378
-            $id = absint($id);
1379
-            // get the ticket for this id
1380
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1381
-            // 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)
1382
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1383
-            foreach ($dtts as $dtt) {
1384
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1385
-            }
1386
-            // 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))
1387
-            $tkt_to_remove->delete_related_permanently('Price');
1388
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1389
-            $tkt_to_remove->delete_permanently();
1390
-        }
1391
-        return array($saved_dtt, $saved_tickets);
1392
-    }
1393
-
1394
-
1395
-    /**
1396
-     * This attaches a list of given prices to a ticket.
1397
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1398
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1399
-     * price info and prices are automatically "archived" via the ticket.
1400
-     *
1401
-     * @access  private
1402
-     * @param array     $prices     Array of prices from the form.
1403
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1404
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1405
-     * @return  void
1406
-     * @throws EE_Error
1407
-     * @throws InvalidArgumentException
1408
-     * @throws InvalidDataTypeException
1409
-     * @throws InvalidInterfaceException
1410
-     * @throws ReflectionException
1411
-     */
1412
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1413
-    {
1414
-        foreach ($prices as $row => $prc) {
1415
-            $PRC_values = array(
1416
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1417
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1418
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1419
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1420
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1421
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1422
-                'PRC_order'      => $row,
1423
-            );
1424
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1425
-                $PRC_values['PRC_ID'] = 0;
1426
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1427
-            } else {
1428
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1429
-                // update this price with new values
1430
-                foreach ($PRC_values as $field => $newprc) {
1431
-                    $PRC->set($field, $newprc);
1432
-                }
1433
-                $PRC->save();
1434
-            }
1435
-            $ticket->_add_relation_to($PRC, 'Price');
1436
-        }
1437
-    }
1438
-
1439
-
1440
-    /**
1441
-     * Add in our autosave ajax handlers
1442
-     *
1443
-     */
1444
-    protected function _ee_autosave_create_new()
1445
-    {
1446
-    }
1447
-
1448
-
1449
-    /**
1450
-     * More autosave handlers.
1451
-     */
1452
-    protected function _ee_autosave_edit()
1453
-    {
1454
-    }
1455
-
1456
-
1457
-    /**
1458
-     *    _generate_publish_box_extra_content
1459
-     *
1460
-     * @throws DomainException
1461
-     * @throws EE_Error
1462
-     * @throws InvalidArgumentException
1463
-     * @throws InvalidDataTypeException
1464
-     * @throws InvalidInterfaceException
1465
-     * @throws ReflectionException
1466
-     */
1467
-    private function _generate_publish_box_extra_content()
1468
-    {
1469
-        // load formatter helper
1470
-        // args for getting related registrations
1471
-        $approved_query_args = array(
1472
-            array(
1473
-                'REG_deleted' => 0,
1474
-                'STS_ID'      => EEM_Registration::status_id_approved,
1475
-            ),
1476
-        );
1477
-        $not_approved_query_args = array(
1478
-            array(
1479
-                'REG_deleted' => 0,
1480
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1481
-            ),
1482
-        );
1483
-        $pending_payment_query_args = array(
1484
-            array(
1485
-                'REG_deleted' => 0,
1486
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1487
-            ),
1488
-        );
1489
-        // publish box
1490
-        $publish_box_extra_args = array(
1491
-            'view_approved_reg_url'        => add_query_arg(
1492
-                array(
1493
-                    'action'      => 'default',
1494
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1495
-                    '_reg_status' => EEM_Registration::status_id_approved,
1496
-                ),
1497
-                REG_ADMIN_URL
1498
-            ),
1499
-            'view_not_approved_reg_url'    => add_query_arg(
1500
-                array(
1501
-                    'action'      => 'default',
1502
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1503
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1504
-                ),
1505
-                REG_ADMIN_URL
1506
-            ),
1507
-            'view_pending_payment_reg_url' => add_query_arg(
1508
-                array(
1509
-                    'action'      => 'default',
1510
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1511
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1512
-                ),
1513
-                REG_ADMIN_URL
1514
-            ),
1515
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1516
-                'Registration',
1517
-                $approved_query_args
1518
-            ),
1519
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1520
-                'Registration',
1521
-                $not_approved_query_args
1522
-            ),
1523
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1524
-                'Registration',
1525
-                $pending_payment_query_args
1526
-            ),
1527
-            'misc_pub_section_class'       => apply_filters(
1528
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1529
-                'misc-pub-section'
1530
-            ),
1531
-        );
1532
-        ob_start();
1533
-        do_action(
1534
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1535
-            $this->_cpt_model_obj
1536
-        );
1537
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1538
-        // load template
1539
-        EEH_Template::display_template(
1540
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1541
-            $publish_box_extra_args
1542
-        );
1543
-    }
1544
-
1545
-
1546
-    /**
1547
-     * @return EE_Event
1548
-     */
1549
-    public function get_event_object()
1550
-    {
1551
-        return $this->_cpt_model_obj;
1552
-    }
1553
-
1554
-
1555
-
1556
-
1557
-    /** METABOXES * */
1558
-    /**
1559
-     * _register_event_editor_meta_boxes
1560
-     * add all metaboxes related to the event_editor
1561
-     *
1562
-     * @return void
1563
-     * @throws EE_Error
1564
-     * @throws InvalidArgumentException
1565
-     * @throws InvalidDataTypeException
1566
-     * @throws InvalidInterfaceException
1567
-     * @throws ReflectionException
1568
-     */
1569
-    protected function _register_event_editor_meta_boxes()
1570
-    {
1571
-        $this->verify_cpt_object();
1572
-        if (EE_Registry::instance()->CFG->admin->useAdvancedEditor()) {
1573
-            add_action(
1574
-                'add_meta_boxes_espresso_events',
1575
-                function () {
1576
-                    global $current_screen;
1577
-                    remove_meta_box( 'authordiv' , $current_screen , 'normal' );
1578
-                },
1579
-                99
1580
-            );
1581
-            return;
1582
-        }
1583
-        add_meta_box(
1584
-            'espresso_event_editor_tickets',
1585
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1586
-            [$this, 'ticket_metabox'],
1587
-            $this->page_slug,
1588
-            'normal',
1589
-            'high'
1590
-        );
1591
-        add_meta_box(
1592
-            'espresso_event_editor_event_options',
1593
-            esc_html__('Event Registration Options', 'event_espresso'),
1594
-            array($this, 'registration_options_meta_box'),
1595
-            $this->page_slug,
1596
-            'side'
1597
-        );
1598
-        // NOTE: if you're looking for other metaboxes in here,
1599
-        // where a metabox has a related management page in the admin
1600
-        // you will find it setup in the related management page's "_Hooks" file.
1601
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1602
-    }
1603
-
1604
-
1605
-    /**
1606
-     * @throws DomainException
1607
-     * @throws EE_Error
1608
-     * @throws InvalidArgumentException
1609
-     * @throws InvalidDataTypeException
1610
-     * @throws InvalidInterfaceException
1611
-     * @throws ReflectionException
1612
-     */
1613
-    public function ticket_metabox()
1614
-    {
1615
-        $existing_datetime_ids = $existing_ticket_ids = array();
1616
-        // defaults for template args
1617
-        $template_args = array(
1618
-            'existing_datetime_ids'    => '',
1619
-            'event_datetime_help_link' => '',
1620
-            'ticket_options_help_link' => '',
1621
-            'time'                     => null,
1622
-            'ticket_rows'              => '',
1623
-            'existing_ticket_ids'      => '',
1624
-            'total_ticket_rows'        => 1,
1625
-            'ticket_js_structure'      => '',
1626
-            'trash_icon'               => 'ee-lock-icon',
1627
-            'disabled'                 => '',
1628
-        );
1629
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1630
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1631
-        /**
1632
-         * 1. Start with retrieving Datetimes
1633
-         * 2. Fore each datetime get related tickets
1634
-         * 3. For each ticket get related prices
1635
-         */
1636
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1637
-        /** @type EE_Datetime $first_datetime */
1638
-        $first_datetime = reset($times);
1639
-        // do we get related tickets?
1640
-        if ($first_datetime instanceof EE_Datetime
1641
-            && $first_datetime->ID() !== 0
1642
-        ) {
1643
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1644
-            $template_args['time'] = $first_datetime;
1645
-            $related_tickets = $first_datetime->tickets(
1646
-                array(
1647
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1648
-                    'default_where_conditions' => 'none',
1649
-                )
1650
-            );
1651
-            if (! empty($related_tickets)) {
1652
-                $template_args['total_ticket_rows'] = count($related_tickets);
1653
-                $row = 0;
1654
-                foreach ($related_tickets as $ticket) {
1655
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1656
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1657
-                    $row++;
1658
-                }
1659
-            } else {
1660
-                $template_args['total_ticket_rows'] = 1;
1661
-                /** @type EE_Ticket $ticket */
1662
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1663
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1664
-            }
1665
-        } else {
1666
-            $template_args['time'] = $times[0];
1667
-            /** @type EE_Ticket $ticket */
1668
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1669
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1670
-            // NOTE: we're just sending the first default row
1671
-            // (decaf can't manage default tickets so this should be sufficient);
1672
-        }
1673
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1674
-            'event_editor_event_datetimes_help_tab'
1675
-        );
1676
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1677
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1678
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1679
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1680
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1681
-            true
1682
-        );
1683
-        $template = apply_filters(
1684
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1685
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1686
-        );
1687
-        EEH_Template::display_template($template, $template_args);
1688
-    }
1689
-
1690
-
1691
-    /**
1692
-     * Setup an individual ticket form for the decaf event editor page
1693
-     *
1694
-     * @access private
1695
-     * @param EE_Ticket $ticket   the ticket object
1696
-     * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1697
-     * @param int       $row
1698
-     * @return string generated html for the ticket row.
1699
-     * @throws DomainException
1700
-     * @throws EE_Error
1701
-     * @throws InvalidArgumentException
1702
-     * @throws InvalidDataTypeException
1703
-     * @throws InvalidInterfaceException
1704
-     * @throws ReflectionException
1705
-     */
1706
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1707
-    {
1708
-        $template_args = array(
1709
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1710
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1711
-                : '',
1712
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1713
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1714
-            'TKT_name'            => $ticket->get('TKT_name'),
1715
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1716
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1717
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1718
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1719
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1720
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1721
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1722
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1723
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1724
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1725
-                : ' disabled=disabled',
1726
-        );
1727
-        $price = $ticket->ID() !== 0
1728
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1729
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1730
-        $price_args = array(
1731
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1732
-            'PRC_amount'            => $price->get('PRC_amount'),
1733
-            'PRT_ID'                => $price->get('PRT_ID'),
1734
-            'PRC_ID'                => $price->get('PRC_ID'),
1735
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1736
-        );
1737
-        // make sure we have default start and end dates if skeleton
1738
-        // handle rows that should NOT be empty
1739
-        if (empty($template_args['TKT_start_date'])) {
1740
-            // if empty then the start date will be now.
1741
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1742
-        }
1743
-        if (empty($template_args['TKT_end_date'])) {
1744
-            // get the earliest datetime (if present);
1745
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1746
-                ? $this->_cpt_model_obj->get_first_related(
1747
-                    'Datetime',
1748
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1749
-                )
1750
-                : null;
1751
-            if (! empty($earliest_dtt)) {
1752
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1753
-            } else {
1754
-                $template_args['TKT_end_date'] = date(
1755
-                    'Y-m-d h:i a',
1756
-                    mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1757
-                );
1758
-            }
1759
-        }
1760
-        $template_args = array_merge($template_args, $price_args);
1761
-        $template = apply_filters(
1762
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1763
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1764
-            $ticket
1765
-        );
1766
-        return EEH_Template::display_template($template, $template_args, true);
1767
-    }
1768
-
1769
-
1770
-    /**
1771
-     * @throws DomainException
1772
-     * @throws EE_Error
1773
-     */
1774
-    public function registration_options_meta_box()
1775
-    {
1776
-        $yes_no_values = array(
1777
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1778
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1779
-        );
1780
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1781
-            array(
1782
-                EEM_Registration::status_id_cancelled,
1783
-                EEM_Registration::status_id_declined,
1784
-                EEM_Registration::status_id_incomplete,
1785
-            ),
1786
-            true
1787
-        );
1788
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1789
-        $template_args['_event'] = $this->_cpt_model_obj;
1790
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1791
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1792
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1793
-            'default_reg_status',
1794
-            $default_reg_status_values,
1795
-            $this->_cpt_model_obj->default_registration_status()
1796
-        );
1797
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1798
-            'display_desc',
1799
-            $yes_no_values,
1800
-            $this->_cpt_model_obj->display_description()
1801
-        );
1802
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1803
-            'display_ticket_selector',
1804
-            $yes_no_values,
1805
-            $this->_cpt_model_obj->display_ticket_selector(),
1806
-            '',
1807
-            '',
1808
-            false
1809
-        );
1810
-        $template_args['additional_registration_options'] = apply_filters(
1811
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1812
-            '',
1813
-            $template_args,
1814
-            $yes_no_values,
1815
-            $default_reg_status_values
1816
-        );
1817
-        EEH_Template::display_template(
1818
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1819
-            $template_args
1820
-        );
1821
-    }
1822
-
1823
-
1824
-    /**
1825
-     * _get_events()
1826
-     * This method simply returns all the events (for the given _view and paging)
1827
-     *
1828
-     * @access public
1829
-     * @param int  $per_page     count of items per page (20 default);
1830
-     * @param int  $current_page what is the current page being viewed.
1831
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1832
-     *                           If FALSE then we return an array of event objects
1833
-     *                           that match the given _view and paging parameters.
1834
-     * @return array an array of event objects.
1835
-     * @throws EE_Error
1836
-     * @throws InvalidArgumentException
1837
-     * @throws InvalidDataTypeException
1838
-     * @throws InvalidInterfaceException
1839
-     * @throws ReflectionException
1840
-     * @throws Exception
1841
-     * @throws Exception
1842
-     * @throws Exception
1843
-     */
1844
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1845
-    {
1846
-        $EEME = $this->_event_model();
1847
-        $offset = ($current_page - 1) * $per_page;
1848
-        $limit = $count ? null : $offset . ',' . $per_page;
1849
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1850
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1851
-        if (isset($this->_req_data['month_range'])) {
1852
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1853
-            // simulate the FIRST day of the month, that fixes issues for months like February
1854
-            // where PHP doesn't know what to assume for date.
1855
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1856
-            $month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1857
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1858
-        }
1859
-        $where = array();
1860
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1861
-        // determine what post_status our condition will have for the query.
1862
-        switch ($status) {
1863
-            case 'month':
1864
-            case 'today':
1865
-            case null:
1866
-            case 'all':
1867
-                break;
1868
-            case 'draft':
1869
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1870
-                break;
1871
-            default:
1872
-                $where['status'] = $status;
1873
-        }
1874
-        // categories?
1875
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1876
-            ? $this->_req_data['EVT_CAT'] : null;
1877
-        if (! empty($category)) {
1878
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1879
-            $where['Term_Taxonomy.term_id'] = $category;
1880
-        }
1881
-        // date where conditions
1882
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1883
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1884
-            $DateTime = new DateTime(
1885
-                $year_r . '-' . $month_r . '-01 00:00:00',
1886
-                new DateTimeZone('UTC')
1887
-            );
1888
-            $start = $DateTime->getTimestamp();
1889
-            // set the datetime to be the end of the month
1890
-            $DateTime->setDate(
1891
-                $year_r,
1892
-                $month_r,
1893
-                $DateTime->format('t')
1894
-            )->setTime(23, 59, 59);
1895
-            $end = $DateTime->getTimestamp();
1896
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1897
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1898
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1899
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1900
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1901
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1902
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1903
-            $now = date('Y-m-01');
1904
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1905
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1906
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1907
-                            ->setTime(23, 59, 59)
1908
-                            ->format(implode(' ', $start_formats));
1909
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1910
-        }
1911
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1912
-            $where['EVT_wp_user'] = get_current_user_id();
1913
-        } elseif (! isset($where['status'])
1914
-            && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1915
-        ) {
1916
-            $where['OR'] = array(
1917
-                'status*restrict_private' => array('!=', 'private'),
1918
-                'AND'                     => array(
1919
-                    'status*inclusive' => array('=', 'private'),
1920
-                    'EVT_wp_user'      => get_current_user_id(),
1921
-                ),
1922
-            );
1923
-        }
1924
-
1925
-        if (isset($this->_req_data['EVT_wp_user'])
1926
-            && (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
1927
-            && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1928
-        ) {
1929
-            $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1930
-        }
1931
-        // search query handling
1932
-        if (isset($this->_req_data['s'])) {
1933
-            $search_string = '%' . $this->_req_data['s'] . '%';
1934
-            $where['OR'] = array(
1935
-                'EVT_name'       => array('LIKE', $search_string),
1936
-                'EVT_desc'       => array('LIKE', $search_string),
1937
-                'EVT_short_desc' => array('LIKE', $search_string),
1938
-            );
1939
-        }
1940
-        // filter events by venue.
1941
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1942
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1943
-        }
1944
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1945
-        $query_params = apply_filters(
1946
-            'FHEE__Events_Admin_Page__get_events__query_params',
1947
-            array(
1948
-                $where,
1949
-                'limit'    => $limit,
1950
-                'order_by' => $orderby,
1951
-                'order'    => $order,
1952
-                'group_by' => 'EVT_ID',
1953
-            ),
1954
-            $this->_req_data
1955
-        );
1956
-
1957
-        // let's first check if we have special requests coming in.
1958
-        if (isset($this->_req_data['active_status'])) {
1959
-            switch ($this->_req_data['active_status']) {
1960
-                case 'upcoming':
1961
-                    return $EEME->get_upcoming_events($query_params, $count);
1962
-                    break;
1963
-                case 'expired':
1964
-                    return $EEME->get_expired_events($query_params, $count);
1965
-                    break;
1966
-                case 'active':
1967
-                    return $EEME->get_active_events($query_params, $count);
1968
-                    break;
1969
-                case 'inactive':
1970
-                    return $EEME->get_inactive_events($query_params, $count);
1971
-                    break;
1972
-            }
1973
-        }
1974
-
1975
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1976
-        return $events;
1977
-    }
1978
-
1979
-
1980
-    /**
1981
-     * handling for WordPress CPT actions (trash, restore, delete)
1982
-     *
1983
-     * @param string $post_id
1984
-     * @throws EE_Error
1985
-     * @throws InvalidArgumentException
1986
-     * @throws InvalidDataTypeException
1987
-     * @throws InvalidInterfaceException
1988
-     * @throws ReflectionException
1989
-     */
1990
-    public function trash_cpt_item($post_id)
1991
-    {
1992
-        $this->_req_data['EVT_ID'] = $post_id;
1993
-        $this->_trash_or_restore_event('trash', false);
1994
-    }
1995
-
1996
-
1997
-    /**
1998
-     * @param string $post_id
1999
-     * @throws EE_Error
2000
-     * @throws InvalidArgumentException
2001
-     * @throws InvalidDataTypeException
2002
-     * @throws InvalidInterfaceException
2003
-     * @throws ReflectionException
2004
-     */
2005
-    public function restore_cpt_item($post_id)
2006
-    {
2007
-        $this->_req_data['EVT_ID'] = $post_id;
2008
-        $this->_trash_or_restore_event('draft', false);
2009
-    }
2010
-
2011
-
2012
-    /**
2013
-     * @param string $post_id
2014
-     * @throws EE_Error
2015
-     * @throws InvalidArgumentException
2016
-     * @throws InvalidDataTypeException
2017
-     * @throws InvalidInterfaceException
2018
-     * @throws ReflectionException
2019
-     */
2020
-    public function delete_cpt_item($post_id)
2021
-    {
2022
-        $this->_req_data['EVT_ID'] = $post_id;
2023
-        $this->_delete_event(false);
2024
-    }
2025
-
2026
-
2027
-    /**
2028
-     * _trash_or_restore_event
2029
-     *
2030
-     * @access protected
2031
-     * @param string $event_status
2032
-     * @param bool   $redirect_after
2033
-     * @throws EE_Error
2034
-     * @throws InvalidArgumentException
2035
-     * @throws InvalidDataTypeException
2036
-     * @throws InvalidInterfaceException
2037
-     * @throws ReflectionException
2038
-     */
2039
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2040
-    {
2041
-        // determine the event id and set to array.
2042
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2043
-        // loop thru events
2044
-        if ($EVT_ID) {
2045
-            // clean status
2046
-            $event_status = sanitize_key($event_status);
2047
-            // grab status
2048
-            if (! empty($event_status)) {
2049
-                $success = $this->_change_event_status($EVT_ID, $event_status);
2050
-            } else {
2051
-                $success = false;
2052
-                $msg = esc_html__(
2053
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2054
-                    'event_espresso'
2055
-                );
2056
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2057
-            }
2058
-        } else {
2059
-            $success = false;
2060
-            $msg = esc_html__(
2061
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2062
-                'event_espresso'
2063
-            );
2064
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2065
-        }
2066
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2067
-        if ($redirect_after) {
2068
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
2069
-        }
2070
-    }
2071
-
2072
-
2073
-    /**
2074
-     * _trash_or_restore_events
2075
-     *
2076
-     * @access protected
2077
-     * @param string $event_status
2078
-     * @return void
2079
-     * @throws EE_Error
2080
-     * @throws InvalidArgumentException
2081
-     * @throws InvalidDataTypeException
2082
-     * @throws InvalidInterfaceException
2083
-     * @throws ReflectionException
2084
-     */
2085
-    protected function _trash_or_restore_events($event_status = 'trash')
2086
-    {
2087
-        // clean status
2088
-        $event_status = sanitize_key($event_status);
2089
-        // grab status
2090
-        if (! empty($event_status)) {
2091
-            $success = true;
2092
-            // determine the event id and set to array.
2093
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2094
-            // loop thru events
2095
-            foreach ($EVT_IDs as $EVT_ID) {
2096
-                if ($EVT_ID = absint($EVT_ID)) {
2097
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2098
-                    $success = $results !== false ? $success : false;
2099
-                } else {
2100
-                    $msg = sprintf(
2101
-                        esc_html__(
2102
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2103
-                            'event_espresso'
2104
-                        ),
2105
-                        $EVT_ID
2106
-                    );
2107
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2108
-                    $success = false;
2109
-                }
2110
-            }
2111
-        } else {
2112
-            $success = false;
2113
-            $msg = esc_html__(
2114
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2115
-                'event_espresso'
2116
-            );
2117
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2118
-        }
2119
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2120
-        $success = $success ? 2 : false;
2121
-        $action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2122
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2123
-    }
2124
-
2125
-
2126
-    /**
2127
-     * _trash_or_restore_events
2128
-     *
2129
-     * @access  private
2130
-     * @param int    $EVT_ID
2131
-     * @param string $event_status
2132
-     * @return bool
2133
-     * @throws EE_Error
2134
-     * @throws InvalidArgumentException
2135
-     * @throws InvalidDataTypeException
2136
-     * @throws InvalidInterfaceException
2137
-     * @throws ReflectionException
2138
-     */
2139
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2140
-    {
2141
-        // grab event id
2142
-        if (! $EVT_ID) {
2143
-            $msg = esc_html__(
2144
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2145
-                'event_espresso'
2146
-            );
2147
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2148
-            return false;
2149
-        }
2150
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2151
-        // clean status
2152
-        $event_status = sanitize_key($event_status);
2153
-        // grab status
2154
-        if (empty($event_status)) {
2155
-            $msg = esc_html__(
2156
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2157
-                'event_espresso'
2158
-            );
2159
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2160
-            return false;
2161
-        }
2162
-        // was event trashed or restored ?
2163
-        switch ($event_status) {
2164
-            case 'draft':
2165
-                $action = 'restored from the trash';
2166
-                $hook = 'AHEE_event_restored_from_trash';
2167
-                break;
2168
-            case 'trash':
2169
-                $action = 'moved to the trash';
2170
-                $hook = 'AHEE_event_moved_to_trash';
2171
-                break;
2172
-            default:
2173
-                $action = 'updated';
2174
-                $hook = false;
2175
-        }
2176
-        // use class to change status
2177
-        $this->_cpt_model_obj->set_status($event_status);
2178
-        $success = $this->_cpt_model_obj->save();
2179
-        if ($success === false) {
2180
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2181
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2182
-            return false;
2183
-        }
2184
-        if ($hook) {
2185
-            do_action($hook);
2186
-        }
2187
-        return true;
2188
-    }
2189
-
2190
-
2191
-    /**
2192
-     * _delete_event
2193
-     *
2194
-     * @access protected
2195
-     * @param bool $redirect_after
2196
-     * @throws EE_Error
2197
-     * @throws InvalidArgumentException
2198
-     * @throws InvalidDataTypeException
2199
-     * @throws InvalidInterfaceException
2200
-     * @throws ReflectionException
2201
-     */
2202
-    protected function _delete_event($redirect_after = true)
2203
-    {
2204
-        // determine the event id and set to array.
2205
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2206
-        $EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2207
-        // loop thru events
2208
-        if ($EVT_ID) {
2209
-            $success = $this->_permanently_delete_event($EVT_ID);
2210
-            // get list of events with no prices
2211
-            $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2212
-            // remove this event from the list of events with no prices
2213
-            if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2214
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2215
-            }
2216
-            update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2217
-        } else {
2218
-            $success = false;
2219
-            $msg = esc_html__(
2220
-                'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2221
-                'event_espresso'
2222
-            );
2223
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2224
-        }
2225
-        if ($redirect_after) {
2226
-            $this->_redirect_after_action(
2227
-                $success,
2228
-                'Event',
2229
-                'deleted',
2230
-                array('action' => 'default', 'status' => 'trash')
2231
-            );
2232
-        }
2233
-    }
2234
-
2235
-
2236
-    /**
2237
-     * _delete_events
2238
-     *
2239
-     * @access protected
2240
-     * @return void
2241
-     * @throws EE_Error
2242
-     * @throws InvalidArgumentException
2243
-     * @throws InvalidDataTypeException
2244
-     * @throws InvalidInterfaceException
2245
-     * @throws ReflectionException
2246
-     */
2247
-    protected function _delete_events()
2248
-    {
2249
-        $success = true;
2250
-        // get list of events with no prices
2251
-        $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2252
-        // determine the event id and set to array.
2253
-        $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2254
-        // loop thru events
2255
-        foreach ($EVT_IDs as $EVT_ID) {
2256
-            $EVT_ID = absint($EVT_ID);
2257
-            if ($EVT_ID) {
2258
-                $results = $this->_permanently_delete_event($EVT_ID);
2259
-                $success = $results !== false ? $success : false;
2260
-                // remove this event from the list of events with no prices
2261
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2262
-            } else {
2263
-                $success = false;
2264
-                $msg = esc_html__(
2265
-                    'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2266
-                    'event_espresso'
2267
-                );
2268
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2269
-            }
2270
-        }
2271
-        update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2272
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2273
-        $success = $success ? 2 : false;
2274
-        $this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2275
-    }
2276
-
2277
-
2278
-    /**
2279
-     * _permanently_delete_event
2280
-     *
2281
-     * @access  private
2282
-     * @param int $EVT_ID
2283
-     * @return bool
2284
-     * @throws EE_Error
2285
-     * @throws InvalidArgumentException
2286
-     * @throws InvalidDataTypeException
2287
-     * @throws InvalidInterfaceException
2288
-     * @throws ReflectionException
2289
-     */
2290
-    private function _permanently_delete_event($EVT_ID = 0)
2291
-    {
2292
-        // grab event id
2293
-        if (! $EVT_ID) {
2294
-            $msg = esc_html__(
2295
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2296
-                'event_espresso'
2297
-            );
2298
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2299
-            return false;
2300
-        }
2301
-        if (! $this->_cpt_model_obj instanceof EE_Event
2302
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2303
-        ) {
2304
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2305
-        }
2306
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2307
-            return false;
2308
-        }
2309
-        // need to delete related tickets and prices first.
2310
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2311
-        foreach ($datetimes as $datetime) {
2312
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2313
-            $tickets = $datetime->get_many_related('Ticket');
2314
-            foreach ($tickets as $ticket) {
2315
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2316
-                $ticket->delete_related_permanently('Price');
2317
-                $ticket->delete_permanently();
2318
-            }
2319
-            $datetime->delete();
2320
-        }
2321
-        // what about related venues or terms?
2322
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2323
-        foreach ($venues as $venue) {
2324
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2325
-        }
2326
-        // any attached question groups?
2327
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2328
-        if (! empty($question_groups)) {
2329
-            foreach ($question_groups as $question_group) {
2330
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2331
-            }
2332
-        }
2333
-        // Message Template Groups
2334
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2335
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2336
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2337
-        foreach ($term_taxonomies as $term_taxonomy) {
2338
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2339
-        }
2340
-        $success = $this->_cpt_model_obj->delete_permanently();
2341
-        // did it all go as planned ?
2342
-        if ($success) {
2343
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2344
-            EE_Error::add_success($msg);
2345
-        } else {
2346
-            $msg = sprintf(
2347
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2348
-                $EVT_ID
2349
-            );
2350
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2351
-            return false;
2352
-        }
2353
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2354
-        return true;
2355
-    }
2356
-
2357
-
2358
-    /**
2359
-     * get total number of events
2360
-     *
2361
-     * @access public
2362
-     * @return int
2363
-     * @throws EE_Error
2364
-     * @throws InvalidArgumentException
2365
-     * @throws InvalidDataTypeException
2366
-     * @throws InvalidInterfaceException
2367
-     */
2368
-    public function total_events()
2369
-    {
2370
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2371
-        return $count;
2372
-    }
2373
-
2374
-
2375
-    /**
2376
-     * get total number of draft events
2377
-     *
2378
-     * @access public
2379
-     * @return int
2380
-     * @throws EE_Error
2381
-     * @throws InvalidArgumentException
2382
-     * @throws InvalidDataTypeException
2383
-     * @throws InvalidInterfaceException
2384
-     */
2385
-    public function total_events_draft()
2386
-    {
2387
-        $where = array(
2388
-            'status' => array('IN', array('draft', 'auto-draft')),
2389
-        );
2390
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2391
-        return $count;
2392
-    }
2393
-
2394
-
2395
-    /**
2396
-     * get total number of trashed events
2397
-     *
2398
-     * @access public
2399
-     * @return int
2400
-     * @throws EE_Error
2401
-     * @throws InvalidArgumentException
2402
-     * @throws InvalidDataTypeException
2403
-     * @throws InvalidInterfaceException
2404
-     */
2405
-    public function total_trashed_events()
2406
-    {
2407
-        $where = array(
2408
-            'status' => 'trash',
2409
-        );
2410
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2411
-        return $count;
2412
-    }
2413
-
2414
-
2415
-    /**
2416
-     *    _default_event_settings
2417
-     *    This generates the Default Settings Tab
2418
-     *
2419
-     * @return void
2420
-     * @throws DomainException
2421
-     * @throws EE_Error
2422
-     * @throws InvalidArgumentException
2423
-     * @throws InvalidDataTypeException
2424
-     * @throws InvalidInterfaceException
2425
-     */
2426
-    protected function _default_event_settings()
2427
-    {
2428
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2429
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2430
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2431
-        $this->display_admin_page_with_sidebar();
2432
-    }
2433
-
2434
-
2435
-    /**
2436
-     * Return the form for event settings.
2437
-     *
2438
-     * @return EE_Form_Section_Proper
2439
-     * @throws EE_Error
2440
-     */
2441
-    protected function _default_event_settings_form()
2442
-    {
2443
-        $registration_config = EE_Registry::instance()->CFG->registration;
2444
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2445
-            // exclude
2446
-            array(
2447
-                EEM_Registration::status_id_cancelled,
2448
-                EEM_Registration::status_id_declined,
2449
-                EEM_Registration::status_id_incomplete,
2450
-                EEM_Registration::status_id_wait_list,
2451
-            ),
2452
-            true
2453
-        );
2454
-        return new EE_Form_Section_Proper(
2455
-            array(
2456
-                'name'            => 'update_default_event_settings',
2457
-                'html_id'         => 'update_default_event_settings',
2458
-                'html_class'      => 'form-table',
2459
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2460
-                'subsections'     => apply_filters(
2461
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2462
-                    array(
2463
-                        'default_reg_status'  => new EE_Select_Input(
2464
-                            $registration_stati_for_selection,
2465
-                            array(
2466
-                                'default'         => isset($registration_config->default_STS_ID)
2467
-                                                     && array_key_exists(
2468
-                                                         $registration_config->default_STS_ID,
2469
-                                                         $registration_stati_for_selection
2470
-                                                     )
2471
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2472
-                                    : EEM_Registration::status_id_pending_payment,
2473
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2474
-                                                     . EEH_Template::get_help_tab_link(
2475
-                                                         'default_settings_status_help_tab'
2476
-                                                     ),
2477
-                                'html_help_text'  => esc_html__(
2478
-                                    '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.',
2479
-                                    'event_espresso'
2480
-                                ),
2481
-                            )
2482
-                        ),
2483
-                        'default_max_tickets' => new EE_Integer_Input(
2484
-                            array(
2485
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2486
-                                    ? $registration_config->default_maximum_number_of_tickets
2487
-                                    : EEM_Event::get_default_additional_limit(),
2488
-                                'html_label_text' => esc_html__(
2489
-                                    'Default Maximum Tickets Allowed Per Order:',
2490
-                                    'event_espresso'
2491
-                                )
2492
-                                                     . EEH_Template::get_help_tab_link(
2493
-                                                         'default_maximum_tickets_help_tab"'
2494
-                                                     ),
2495
-                                'html_help_text'  => esc_html__(
2496
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2497
-                                    'event_espresso'
2498
-                                ),
2499
-                            )
2500
-                        ),
2501
-                    )
2502
-                ),
2503
-            )
2504
-        );
2505
-    }
2506
-
2507
-
2508
-    /**
2509
-     * @return void
2510
-     * @throws EE_Error
2511
-     * @throws InvalidArgumentException
2512
-     * @throws InvalidDataTypeException
2513
-     * @throws InvalidInterfaceException
2514
-     */
2515
-    protected function _update_default_event_settings()
2516
-    {
2517
-        $form = $this->_default_event_settings_form();
2518
-        if ($form->was_submitted()) {
2519
-            $form->receive_form_submission();
2520
-            if ($form->is_valid()) {
2521
-                $registration_config = EE_Registry::instance()->CFG->registration;
2522
-                $valid_data = $form->valid_data();
2523
-                if (isset($valid_data['default_reg_status'])) {
2524
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2525
-                }
2526
-                if (isset($valid_data['default_max_tickets'])) {
2527
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2528
-                }
2529
-                do_action(
2530
-                    'AHEE__Events_Admin_Page___update_default_event_settings',
2531
-                    $valid_data,
2532
-                    EE_Registry::instance()->CFG,
2533
-                    $this
2534
-                );
2535
-                // update because data was valid!
2536
-                EE_Registry::instance()->CFG->update_espresso_config();
2537
-                EE_Error::overwrite_success();
2538
-                EE_Error::add_success(
2539
-                    __('Default Event Settings were updated', 'event_espresso')
2540
-                );
2541
-            }
2542
-        }
2543
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2544
-    }
2545
-
2546
-
2547
-    /*************        Templates        *************/
2548
-    protected function _template_settings()
2549
-    {
2550
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2551
-        $this->_template_args['preview_img'] = '<img src="'
2552
-                                               . EVENTS_ASSETS_URL
2553
-                                               . '/images/'
2554
-                                               . 'caffeinated_template_features.jpg" alt="'
2555
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2556
-                                               . '" />';
2557
-        $this->_template_args['preview_text'] = '<strong>'
2558
-                                                . esc_html__(
2559
-                                                    '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.',
2560
-                                                    'event_espresso'
2561
-                                                ) . '</strong>';
2562
-        $this->display_admin_caf_preview_page('template_settings_tab');
2563
-    }
2564
-
2565
-
2566
-    /** Event Category Stuff **/
2567
-    /**
2568
-     * set the _category property with the category object for the loaded page.
2569
-     *
2570
-     * @access private
2571
-     * @return void
2572
-     */
2573
-    private function _set_category_object()
2574
-    {
2575
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2576
-            return;
2577
-        } //already have the category object so get out.
2578
-        // set default category object
2579
-        $this->_set_empty_category_object();
2580
-        // only set if we've got an id
2581
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2582
-            return;
2583
-        }
2584
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2585
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2586
-        if (! empty($term)) {
2587
-            $this->_category->category_name = $term->name;
2588
-            $this->_category->category_identifier = $term->slug;
2589
-            $this->_category->category_desc = $term->description;
2590
-            $this->_category->id = $term->term_id;
2591
-            $this->_category->parent = $term->parent;
2592
-        }
2593
-    }
2594
-
2595
-
2596
-    /**
2597
-     * Clears out category properties.
2598
-     */
2599
-    private function _set_empty_category_object()
2600
-    {
2601
-        $this->_category = new stdClass();
2602
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2603
-        $this->_category->id = $this->_category->parent = 0;
2604
-    }
2605
-
2606
-
2607
-    /**
2608
-     * @throws DomainException
2609
-     * @throws EE_Error
2610
-     * @throws InvalidArgumentException
2611
-     * @throws InvalidDataTypeException
2612
-     * @throws InvalidInterfaceException
2613
-     */
2614
-    protected function _category_list_table()
2615
-    {
2616
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2617
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2618
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2619
-            'add_category',
2620
-            'add_category',
2621
-            array(),
2622
-            'add-new-h2'
2623
-        );
2624
-        $this->display_admin_list_table_page_with_sidebar();
2625
-    }
2626
-
2627
-
2628
-    /**
2629
-     * Output category details view.
2630
-     *
2631
-     * @param string $view
2632
-     * @throws DomainException
2633
-     * @throws EE_Error
2634
-     * @throws InvalidArgumentException
2635
-     * @throws InvalidDataTypeException
2636
-     * @throws InvalidInterfaceException
2637
-     */
2638
-    protected function _category_details($view)
2639
-    {
2640
-        // load formatter helper
2641
-        // load field generator helper
2642
-        $route = $view === 'edit' ? 'update_category' : 'insert_category';
2643
-        $this->_set_add_edit_form_tags($route);
2644
-        $this->_set_category_object();
2645
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2646
-        $delete_action = 'delete_category';
2647
-        // custom redirect
2648
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2649
-            array('action' => 'category_list'),
2650
-            $this->_admin_base_url
2651
-        );
2652
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2653
-        // take care of contents
2654
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2655
-        $this->display_admin_page_with_sidebar();
2656
-    }
2657
-
2658
-
2659
-    /**
2660
-     * Output category details content.
2661
-     *
2662
-     * @throws DomainException
2663
-     */
2664
-    protected function _category_details_content()
2665
-    {
2666
-        $editor_args['category_desc'] = array(
2667
-            'type'          => 'wp_editor',
2668
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2669
-            'class'         => 'my_editor_custom',
2670
-            'wpeditor_args' => array('media_buttons' => false),
2671
-        );
2672
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2673
-        $all_terms = get_terms(
2674
-            array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2675
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2676
-        );
2677
-        // setup category select for term parents.
2678
-        $category_select_values[] = array(
2679
-            'text' => esc_html__('No Parent', 'event_espresso'),
2680
-            'id'   => 0,
2681
-        );
2682
-        foreach ($all_terms as $term) {
2683
-            $category_select_values[] = array(
2684
-                'text' => $term->name,
2685
-                'id'   => $term->term_id,
2686
-            );
2687
-        }
2688
-        $category_select = EEH_Form_Fields::select_input(
2689
-            'category_parent',
2690
-            $category_select_values,
2691
-            $this->_category->parent
2692
-        );
2693
-        $template_args = array(
2694
-            'category'                 => $this->_category,
2695
-            'category_select'          => $category_select,
2696
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2697
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2698
-            'disable'                  => '',
2699
-            'disabled_message'         => false,
2700
-        );
2701
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2702
-        return EEH_Template::display_template($template, $template_args, true);
2703
-    }
2704
-
2705
-
2706
-    /**
2707
-     * Handles deleting categories.
2708
-     */
2709
-    protected function _delete_categories()
2710
-    {
2711
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2712
-            : (array) $this->_req_data['category_id'];
2713
-        foreach ($cat_ids as $cat_id) {
2714
-            $this->_delete_category($cat_id);
2715
-        }
2716
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2717
-        $query_args = array(
2718
-            'action' => 'category_list',
2719
-        );
2720
-        $this->_redirect_after_action(0, '', '', $query_args);
2721
-    }
2722
-
2723
-
2724
-    /**
2725
-     * Handles deleting specific category.
2726
-     *
2727
-     * @param int $cat_id
2728
-     */
2729
-    protected function _delete_category($cat_id)
2730
-    {
2731
-        $cat_id = absint($cat_id);
2732
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2733
-    }
2734
-
2735
-
2736
-    /**
2737
-     * Handles triggering the update or insertion of a new category.
2738
-     *
2739
-     * @param bool $new_category true means we're triggering the insert of a new category.
2740
-     * @throws EE_Error
2741
-     * @throws InvalidArgumentException
2742
-     * @throws InvalidDataTypeException
2743
-     * @throws InvalidInterfaceException
2744
-     */
2745
-    protected function _insert_or_update_category($new_category)
2746
-    {
2747
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2748
-        $success = 0; // we already have a success message so lets not send another.
2749
-        if ($cat_id) {
2750
-            $query_args = array(
2751
-                'action'     => 'edit_category',
2752
-                'EVT_CAT_ID' => $cat_id,
2753
-            );
2754
-        } else {
2755
-            $query_args = array('action' => 'add_category');
2756
-        }
2757
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2758
-    }
2759
-
2760
-
2761
-    /**
2762
-     * Inserts or updates category
2763
-     *
2764
-     * @param bool $update (true indicates we're updating a category).
2765
-     * @return bool|mixed|string
2766
-     */
2767
-    private function _insert_category($update = false)
2768
-    {
2769
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2770
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2771
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2772
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2773
-        if (empty($category_name)) {
2774
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2775
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2776
-            return false;
2777
-        }
2778
-        $term_args = array(
2779
-            'name'        => $category_name,
2780
-            'description' => $category_desc,
2781
-            'parent'      => $category_parent,
2782
-        );
2783
-        // was the category_identifier input disabled?
2784
-        if (isset($this->_req_data['category_identifier'])) {
2785
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2786
-        }
2787
-        $insert_ids = $update
2788
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2789
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2790
-        if (! is_array($insert_ids)) {
2791
-            $msg = esc_html__(
2792
-                'An error occurred and the category has not been saved to the database.',
2793
-                'event_espresso'
2794
-            );
2795
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2796
-        } else {
2797
-            $cat_id = $insert_ids['term_id'];
2798
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2799
-            EE_Error::add_success($msg);
2800
-        }
2801
-        return $cat_id;
2802
-    }
2803
-
2804
-
2805
-    /**
2806
-     * Gets categories or count of categories matching the arguments in the request.
2807
-     *
2808
-     * @param int  $per_page
2809
-     * @param int  $current_page
2810
-     * @param bool $count
2811
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2812
-     * @throws EE_Error
2813
-     * @throws InvalidArgumentException
2814
-     * @throws InvalidDataTypeException
2815
-     * @throws InvalidInterfaceException
2816
-     */
2817
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2818
-    {
2819
-        // testing term stuff
2820
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2821
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2822
-        $limit = ($current_page - 1) * $per_page;
2823
-        $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2824
-        if (isset($this->_req_data['s'])) {
2825
-            $sstr = '%' . $this->_req_data['s'] . '%';
2826
-            $where['OR'] = array(
2827
-                'Term.name'   => array('LIKE', $sstr),
2828
-                'description' => array('LIKE', $sstr),
2829
-            );
2830
-        }
2831
-        $query_params = array(
2832
-            $where,
2833
-            'order_by'   => array($orderby => $order),
2834
-            'limit'      => $limit . ',' . $per_page,
2835
-            'force_join' => array('Term'),
2836
-        );
2837
-        $categories = $count
2838
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2839
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2840
-        return $categories;
2841
-    }
2842
-
2843
-    /* end category stuff */
2844
-    /**************/
2845
-
2846
-
2847
-    /**
2848
-     * Callback for the `ee_save_timezone_setting` ajax action.
2849
-     *
2850
-     * @throws EE_Error
2851
-     * @throws InvalidArgumentException
2852
-     * @throws InvalidDataTypeException
2853
-     * @throws InvalidInterfaceException
2854
-     */
2855
-    public function save_timezonestring_setting()
2856
-    {
2857
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2858
-            ? $this->_req_data['timezone_selected']
2859
-            : '';
2860
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2861
-            EE_Error::add_error(
2862
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2863
-                __FILE__,
2864
-                __FUNCTION__,
2865
-                __LINE__
2866
-            );
2867
-            $this->_template_args['error'] = true;
2868
-            $this->_return_json();
2869
-        }
2870
-
2871
-        update_option('timezone_string', $timezone_string);
2872
-        EE_Error::add_success(
2873
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2874
-        );
2875
-        $this->_template_args['success'] = true;
2876
-        $this->_return_json(true, array('action' => 'create_new'));
2877
-    }
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
+			array(),
566
+			EVENT_ESPRESSO_VERSION
567
+		);
568
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
569
+		wp_enqueue_style('events-admin-css');
570
+		wp_enqueue_style('ee-cat-admin');
571
+		// todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
572
+		// registers for all views
573
+		// scripts
574
+		wp_register_script(
575
+			'event_editor_js',
576
+			EVENTS_ASSETS_URL . 'event_editor.js',
577
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
578
+			EVENT_ESPRESSO_VERSION,
579
+			true
580
+		);
581
+	}
582
+
583
+
584
+	/**
585
+	 * Enqueuing scripts and styles specific to this view
586
+	 */
587
+	public function load_scripts_styles_create_new()
588
+	{
589
+		$this->load_scripts_styles_edit();
590
+	}
591
+
592
+
593
+	/**
594
+	 * Enqueuing scripts and styles specific to this view
595
+	 */
596
+	public function load_scripts_styles_edit()
597
+	{
598
+		// styles
599
+		wp_enqueue_style('espresso-ui-theme');
600
+		wp_register_style(
601
+			'event-editor-css',
602
+			EVENTS_ASSETS_URL . 'event-editor.css',
603
+			array('ee-admin-css'),
604
+			EVENT_ESPRESSO_VERSION
605
+		);
606
+		wp_enqueue_style('event-editor-css');
607
+		// scripts
608
+		wp_register_script(
609
+			'event-datetime-metabox',
610
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
611
+			array('event_editor_js', 'ee-datepicker'),
612
+			EVENT_ESPRESSO_VERSION
613
+		);
614
+		wp_enqueue_script('event-datetime-metabox');
615
+	}
616
+
617
+
618
+	/**
619
+	 * Populating the _views property for the category list table view.
620
+	 */
621
+	protected function _set_list_table_views_category_list()
622
+	{
623
+		$this->_views = array(
624
+			'all' => array(
625
+				'slug'        => 'all',
626
+				'label'       => esc_html__('All', 'event_espresso'),
627
+				'count'       => 0,
628
+				'bulk_action' => array(
629
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
630
+				),
631
+			),
632
+		);
633
+	}
634
+
635
+
636
+	/**
637
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
638
+	 */
639
+	public function admin_init()
640
+	{
641
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
642
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
643
+			'event_espresso'
644
+		);
645
+	}
646
+
647
+
648
+	/**
649
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
650
+	 * group.
651
+	 */
652
+	public function admin_notices()
653
+	{
654
+	}
655
+
656
+
657
+	/**
658
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
659
+	 * this admin page group.
660
+	 */
661
+	public function admin_footer_scripts()
662
+	{
663
+	}
664
+
665
+
666
+	/**
667
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
668
+	 * warning (via EE_Error::add_error());
669
+	 *
670
+	 * @param  EE_Event $event Event object
671
+	 * @param string    $req_type
672
+	 * @return void
673
+	 * @throws EE_Error
674
+	 * @access public
675
+	 */
676
+	public function verify_event_edit($event = null, $req_type = '')
677
+	{
678
+		// don't need to do this when processing
679
+		if (! empty($req_type)) {
680
+			return;
681
+		}
682
+		// no event?
683
+		if (! $event instanceof EE_Event) {
684
+			$event = $this->_cpt_model_obj;
685
+		}
686
+		// STILL no event?
687
+		if (! $event instanceof EE_Event) {
688
+			return;
689
+		}
690
+		$orig_status = $event->status();
691
+		// first check if event is active.
692
+		if ($orig_status === EEM_Event::cancelled
693
+			|| $orig_status === EEM_Event::postponed
694
+			|| $event->is_expired()
695
+			|| $event->is_inactive()
696
+		) {
697
+			return;
698
+		}
699
+		// made it here so it IS active... next check that any of the tickets are sold.
700
+		if ($event->is_sold_out(true)) {
701
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
702
+				EE_Error::add_attention(
703
+					sprintf(
704
+						esc_html__(
705
+							'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.',
706
+							'event_espresso'
707
+						),
708
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
709
+					)
710
+				);
711
+			}
712
+			return;
713
+		}
714
+		if ($orig_status === EEM_Event::sold_out) {
715
+			EE_Error::add_attention(
716
+				sprintf(
717
+					esc_html__(
718
+						'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.',
719
+						'event_espresso'
720
+					),
721
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
722
+				)
723
+			);
724
+		}
725
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
726
+		if (! $event->tickets_on_sale()) {
727
+			return;
728
+		}
729
+		// made it here so show warning
730
+		$this->_edit_event_warning();
731
+	}
732
+
733
+
734
+	/**
735
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
736
+	 * When needed, hook this into a EE_Error::add_error() notice.
737
+	 *
738
+	 * @access protected
739
+	 * @return void
740
+	 */
741
+	protected function _edit_event_warning()
742
+	{
743
+		// we don't want to add warnings during these requests
744
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
745
+			return;
746
+		}
747
+		EE_Error::add_attention(
748
+			sprintf(
749
+				esc_html__(
750
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
751
+					'event_espresso'
752
+				),
753
+				'<a class="espresso-help-tab-lnk">',
754
+				'</a>'
755
+			)
756
+		);
757
+	}
758
+
759
+
760
+	/**
761
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
762
+	 * Otherwise, do the normal logic
763
+	 *
764
+	 * @return string
765
+	 * @throws EE_Error
766
+	 * @throws InvalidArgumentException
767
+	 * @throws InvalidDataTypeException
768
+	 * @throws InvalidInterfaceException
769
+	 */
770
+	protected function _create_new_cpt_item()
771
+	{
772
+		$has_timezone_string = get_option('timezone_string');
773
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
774
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
775
+			EE_Error::add_attention(
776
+				sprintf(
777
+					__(
778
+						'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',
779
+						'event_espresso'
780
+					),
781
+					'<br>',
782
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
783
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
784
+					. '</select>',
785
+					'<button class="button button-secondary timezone-submit">',
786
+					'</button><span class="spinner"></span>'
787
+				),
788
+				__FILE__,
789
+				__FUNCTION__,
790
+				__LINE__
791
+			);
792
+		}
793
+		parent::_create_new_cpt_item();
794
+	}
795
+
796
+
797
+	/**
798
+	 * Sets the _views property for the default route in this admin page group.
799
+	 */
800
+	protected function _set_list_table_views_default()
801
+	{
802
+		$this->_views = array(
803
+			'all'   => array(
804
+				'slug'        => 'all',
805
+				'label'       => esc_html__('View All Events', 'event_espresso'),
806
+				'count'       => 0,
807
+				'bulk_action' => array(
808
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
809
+				),
810
+			),
811
+			'draft' => array(
812
+				'slug'        => 'draft',
813
+				'label'       => esc_html__('Draft', 'event_espresso'),
814
+				'count'       => 0,
815
+				'bulk_action' => array(
816
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
817
+				),
818
+			),
819
+		);
820
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
821
+			$this->_views['trash'] = array(
822
+				'slug'        => 'trash',
823
+				'label'       => esc_html__('Trash', 'event_espresso'),
824
+				'count'       => 0,
825
+				'bulk_action' => array(
826
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
827
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
828
+				),
829
+			);
830
+		}
831
+	}
832
+
833
+
834
+	/**
835
+	 * Provides the legend item array for the default list table view.
836
+	 *
837
+	 * @return array
838
+	 */
839
+	protected function _event_legend_items()
840
+	{
841
+		$items = array(
842
+			'view_details'   => array(
843
+				'class' => 'dashicons dashicons-search',
844
+				'desc'  => esc_html__('View Event', 'event_espresso'),
845
+			),
846
+			'edit_event'     => array(
847
+				'class' => 'ee-icon ee-icon-calendar-edit',
848
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
849
+			),
850
+			'view_attendees' => array(
851
+				'class' => 'dashicons dashicons-groups',
852
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
853
+			),
854
+		);
855
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
856
+		$statuses = array(
857
+			'sold_out_status'  => array(
858
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
859
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
860
+			),
861
+			'active_status'    => array(
862
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
863
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
864
+			),
865
+			'upcoming_status'  => array(
866
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
867
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
868
+			),
869
+			'postponed_status' => array(
870
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
871
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
872
+			),
873
+			'cancelled_status' => array(
874
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
875
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
876
+			),
877
+			'expired_status'   => array(
878
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
879
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
880
+			),
881
+			'inactive_status'  => array(
882
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
883
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
884
+			),
885
+		);
886
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
887
+		return array_merge($items, $statuses);
888
+	}
889
+
890
+
891
+	/**
892
+	 * @return EEM_Event
893
+	 * @throws EE_Error
894
+	 * @throws InvalidArgumentException
895
+	 * @throws InvalidDataTypeException
896
+	 * @throws InvalidInterfaceException
897
+	 * @throws ReflectionException
898
+	 */
899
+	private function _event_model()
900
+	{
901
+		if (! $this->_event_model instanceof EEM_Event) {
902
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
903
+		}
904
+		return $this->_event_model;
905
+	}
906
+
907
+
908
+	/**
909
+	 * Adds extra buttons to the WP CPT permalink field row.
910
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
911
+	 *
912
+	 * @param  string $return    the current html
913
+	 * @param  int    $id        the post id for the page
914
+	 * @param  string $new_title What the title is
915
+	 * @param  string $new_slug  what the slug is
916
+	 * @return string            The new html string for the permalink area
917
+	 */
918
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
919
+	{
920
+		// make sure this is only when editing
921
+		if (! empty($id)) {
922
+			$post = get_post($id);
923
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
924
+					   . esc_html__('Shortcode', 'event_espresso')
925
+					   . '</a> ';
926
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
927
+					   . $post->ID
928
+					   . ']">';
929
+		}
930
+		return $return;
931
+	}
932
+
933
+
934
+	/**
935
+	 * _events_overview_list_table
936
+	 * This contains the logic for showing the events_overview list
937
+	 *
938
+	 * @access protected
939
+	 * @return void
940
+	 * @throws DomainException
941
+	 * @throws EE_Error
942
+	 * @throws InvalidArgumentException
943
+	 * @throws InvalidDataTypeException
944
+	 * @throws InvalidInterfaceException
945
+	 */
946
+	protected function _events_overview_list_table()
947
+	{
948
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
949
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
950
+			? (array) $this->_template_args['after_list_table']
951
+			: array();
952
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
953
+				. EEH_Template::get_button_or_link(
954
+					get_post_type_archive_link('espresso_events'),
955
+					esc_html__('View Event Archive Page', 'event_espresso'),
956
+					'button'
957
+				);
958
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
959
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
960
+			'create_new',
961
+			'add',
962
+			array(),
963
+			'add-new-h2'
964
+		);
965
+		$this->display_admin_list_table_page_with_no_sidebar();
966
+	}
967
+
968
+
969
+	/**
970
+	 * this allows for extra misc actions in the default WP publish box
971
+	 *
972
+	 * @return void
973
+	 * @throws DomainException
974
+	 * @throws EE_Error
975
+	 * @throws InvalidArgumentException
976
+	 * @throws InvalidDataTypeException
977
+	 * @throws InvalidInterfaceException
978
+	 * @throws ReflectionException
979
+	 */
980
+	public function extra_misc_actions_publish_box()
981
+	{
982
+		$this->_generate_publish_box_extra_content();
983
+	}
984
+
985
+
986
+	/**
987
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
988
+	 * saved.
989
+	 * Typically you would use this to save any additional data.
990
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
991
+	 * ALSO very important.  When a post transitions from scheduled to published,
992
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
993
+	 * other meta saves. So MAKE sure that you handle this accordingly.
994
+	 *
995
+	 * @access protected
996
+	 * @abstract
997
+	 * @param string $post_id The ID of the cpt that was saved (so you can link relationally)
998
+	 * @param object $post    The post object of the cpt that was saved.
999
+	 * @return void
1000
+	 * @throws EE_Error
1001
+	 * @throws InvalidArgumentException
1002
+	 * @throws InvalidDataTypeException
1003
+	 * @throws InvalidInterfaceException
1004
+	 * @throws ReflectionException
1005
+	 */
1006
+	protected function _insert_update_cpt_item($post_id, $post)
1007
+	{
1008
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1009
+			// get out we're not processing an event save.
1010
+			return;
1011
+		}
1012
+		$event_values = array(
1013
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1014
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1015
+			'EVT_additional_limit'            => min(
1016
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1017
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1018
+			),
1019
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1020
+				? $this->_req_data['EVT_default_registration_status']
1021
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
1022
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1023
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1024
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1025
+				? $this->_req_data['timezone_string'] : null,
1026
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1027
+				? $this->_req_data['externalURL'] : null,
1028
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1029
+				? $this->_req_data['event_phone'] : null,
1030
+		);
1031
+		// update event
1032
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1033
+		// 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!
1034
+		$get_one_where = array(
1035
+			$this->_event_model()->primary_key_name() => $post_id,
1036
+			'OR'                                      => array(
1037
+				'status'   => $post->post_status,
1038
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1039
+				// but the returned object here has a status of "publish", so use the original post status as well
1040
+				'status*1' => $this->_req_data['original_post_status'],
1041
+			),
1042
+		);
1043
+		$event = $this->_event_model()->get_one(array($get_one_where));
1044
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1045
+		$event_update_callbacks = apply_filters(
1046
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1047
+			array(
1048
+				array($this, '_default_venue_update'),
1049
+				array($this, '_default_tickets_update'),
1050
+			)
1051
+		);
1052
+		$att_success = true;
1053
+		foreach ($event_update_callbacks as $e_callback) {
1054
+			$_success = is_callable($e_callback)
1055
+				? $e_callback($event, $this->_req_data)
1056
+				: false;
1057
+			// if ANY of these updates fail then we want the appropriate global error message
1058
+			$att_success = ! $att_success ? $att_success : $_success;
1059
+		}
1060
+		// any errors?
1061
+		if ($success && false === $att_success) {
1062
+			EE_Error::add_error(
1063
+				esc_html__(
1064
+					'Event Details saved successfully but something went wrong with saving attachments.',
1065
+					'event_espresso'
1066
+				),
1067
+				__FILE__,
1068
+				__FUNCTION__,
1069
+				__LINE__
1070
+			);
1071
+		} elseif ($success === false) {
1072
+			EE_Error::add_error(
1073
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1074
+				__FILE__,
1075
+				__FUNCTION__,
1076
+				__LINE__
1077
+			);
1078
+		}
1079
+	}
1080
+
1081
+
1082
+	/**
1083
+	 * @param int $post_id
1084
+	 * @param int $revision_id
1085
+	 * @throws EE_Error
1086
+	 * @throws InvalidArgumentException
1087
+	 * @throws InvalidDataTypeException
1088
+	 * @throws InvalidInterfaceException
1089
+	 * @throws ReflectionException
1090
+	 * @see parent::restore_item()
1091
+	 */
1092
+	protected function _restore_cpt_item($post_id, $revision_id)
1093
+	{
1094
+		// copy existing event meta to new post
1095
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1096
+		if ($post_evt instanceof EE_Event) {
1097
+			// meta revision restore
1098
+			$post_evt->restore_revision($revision_id);
1099
+			// related objs restore
1100
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1101
+		}
1102
+	}
1103
+
1104
+
1105
+	/**
1106
+	 * Attach the venue to the Event
1107
+	 *
1108
+	 * @param EE_Event $evtobj Event Object to add the venue to
1109
+	 * @param array    $data   The request data from the form
1110
+	 * @return bool           Success or fail.
1111
+	 * @throws EE_Error
1112
+	 * @throws InvalidArgumentException
1113
+	 * @throws InvalidDataTypeException
1114
+	 * @throws InvalidInterfaceException
1115
+	 * @throws ReflectionException
1116
+	 */
1117
+	protected function _default_venue_update(EE_Event $evtobj, $data)
1118
+	{
1119
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1120
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1121
+		$rows_affected = null;
1122
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1123
+		// very important.  If we don't have a venue name...
1124
+		// then we'll get out because not necessary to create empty venue
1125
+		if (empty($data['venue_title'])) {
1126
+			return false;
1127
+		}
1128
+		$venue_array = array(
1129
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1130
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1131
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1132
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1133
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1134
+				: null,
1135
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1136
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1137
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1138
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1139
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1140
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1141
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1142
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1143
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1144
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1145
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1146
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1147
+			'status'              => 'publish',
1148
+		);
1149
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1150
+		if (! empty($venue_id)) {
1151
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1152
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1153
+			// 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.
1154
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1155
+			return $rows_affected > 0;
1156
+		}
1157
+		// we insert the venue
1158
+		$venue_id = $venue_model->insert($venue_array);
1159
+		$evtobj->_add_relation_to($venue_id, 'Venue');
1160
+		return ! empty($venue_id) ? true : false;
1161
+		// when we have the ancestor come in it's already been handled by the revision save.
1162
+	}
1163
+
1164
+
1165
+	/**
1166
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1167
+	 *
1168
+	 * @param EE_Event $evtobj The Event object we're attaching data to
1169
+	 * @param array    $data   The request data from the form
1170
+	 * @return array
1171
+	 * @throws EE_Error
1172
+	 * @throws InvalidArgumentException
1173
+	 * @throws InvalidDataTypeException
1174
+	 * @throws InvalidInterfaceException
1175
+	 * @throws ReflectionException
1176
+	 * @throws Exception
1177
+	 */
1178
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1179
+	{
1180
+		if (EE_Registry::instance()->CFG->admin->useAdvancedEditor()) {
1181
+			return [];
1182
+		}
1183
+		$success = true;
1184
+		$saved_dtt = null;
1185
+		$saved_tickets = array();
1186
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1187
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1188
+			// trim all values to ensure any excess whitespace is removed.
1189
+			$dtt = array_map('trim', $dtt);
1190
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1191
+				: $dtt['DTT_EVT_start'];
1192
+			$datetime_values = array(
1193
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1194
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1195
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1196
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1197
+				'DTT_order'     => $row,
1198
+			);
1199
+			// 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.
1200
+			if (! empty($dtt['DTT_ID'])) {
1201
+				$DTM = EE_Registry::instance()
1202
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1203
+								  ->get_one_by_ID($dtt['DTT_ID']);
1204
+				$DTM->set_date_format($incoming_date_formats[0]);
1205
+				$DTM->set_time_format($incoming_date_formats[1]);
1206
+				foreach ($datetime_values as $field => $value) {
1207
+					$DTM->set($field, $value);
1208
+				}
1209
+				// 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.
1210
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1211
+			} else {
1212
+				$DTM = EE_Registry::instance()->load_class(
1213
+					'Datetime',
1214
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1215
+					false,
1216
+					false
1217
+				);
1218
+				foreach ($datetime_values as $field => $value) {
1219
+					$DTM->set($field, $value);
1220
+				}
1221
+			}
1222
+			$DTM->save();
1223
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1224
+			// load DTT helper
1225
+			// 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.
1226
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1227
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1228
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1229
+				$DTT->save();
1230
+			}
1231
+			// 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.
1232
+			$saved_dtt = $DTT;
1233
+			$success = ! $success ? $success : $DTT;
1234
+			// if ANY of these updates fail then we want the appropriate global error message.
1235
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1236
+		}
1237
+		// no dtts get deleted so we don't do any of that logic here.
1238
+		// update tickets next
1239
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1240
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1241
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1242
+			$update_prices = false;
1243
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1244
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1245
+			// trim inputs to ensure any excess whitespace is removed.
1246
+			$tkt = array_map('trim', $tkt);
1247
+			if (empty($tkt['TKT_start_date'])) {
1248
+				// let's use now in the set timezone.
1249
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1250
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1251
+			}
1252
+			if (empty($tkt['TKT_end_date'])) {
1253
+				// use the start date of the first datetime
1254
+				$dtt = $evtobj->first_datetime();
1255
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1256
+					$incoming_date_formats[0],
1257
+					$incoming_date_formats[1]
1258
+				);
1259
+			}
1260
+			$TKT_values = array(
1261
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1262
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1263
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1264
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1265
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1266
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1267
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1268
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1269
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1270
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1271
+				'TKT_row'         => $row,
1272
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1273
+				'TKT_price'       => $ticket_price,
1274
+			);
1275
+			// 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.
1276
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1277
+				$TKT_values['TKT_ID'] = 0;
1278
+				$TKT_values['TKT_is_default'] = 0;
1279
+				$TKT_values['TKT_price'] = $ticket_price;
1280
+				$update_prices = true;
1281
+			}
1282
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1283
+			// 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.
1284
+			// 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.
1285
+			if (! empty($tkt['TKT_ID'])) {
1286
+				$TKT = EE_Registry::instance()
1287
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1288
+								  ->get_one_by_ID($tkt['TKT_ID']);
1289
+				if ($TKT instanceof EE_Ticket) {
1290
+					$ticket_sold = $TKT->count_related(
1291
+						'Registration',
1292
+						array(
1293
+							array(
1294
+								'STS_ID' => array(
1295
+									'NOT IN',
1296
+									array(EEM_Registration::status_id_incomplete),
1297
+								),
1298
+							),
1299
+						)
1300
+					) > 0;
1301
+					// let's just check the total price for the existing ticket and determine if it matches the new
1302
+					// total price.  if they are different then we create a new ticket (if tickets sold)
1303
+					// if they aren't different then we go ahead and modify existing ticket.
1304
+					$create_new_TKT = $ticket_sold && ! $TKT->deleted() && EEH_Money::compare_floats(
1305
+						$ticket_price,
1306
+						$TKT->get('TKT_price'),
1307
+						'!=='
1308
+					);
1309
+					$TKT->set_date_format($incoming_date_formats[0]);
1310
+					$TKT->set_time_format($incoming_date_formats[1]);
1311
+					// set new values
1312
+					foreach ($TKT_values as $field => $value) {
1313
+						if ($field === 'TKT_qty') {
1314
+							$TKT->set_qty($value);
1315
+						} else {
1316
+							$TKT->set($field, $value);
1317
+						}
1318
+					}
1319
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1320
+					if ($create_new_TKT) {
1321
+						// archive the old ticket first
1322
+						$TKT->set('TKT_deleted', 1);
1323
+						$TKT->save();
1324
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1325
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1326
+						// 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.
1327
+						$TKT = clone $TKT;
1328
+						$TKT->set('TKT_ID', 0);
1329
+						$TKT->set('TKT_deleted', 0);
1330
+						$TKT->set('TKT_price', $ticket_price);
1331
+						$TKT->set('TKT_sold', 0);
1332
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1333
+						$update_prices = true;
1334
+					}
1335
+					// make sure price is set if it hasn't been already
1336
+					$TKT->set('TKT_price', $ticket_price);
1337
+				}
1338
+			} else {
1339
+				// no TKT_id so a new TKT
1340
+				$TKT_values['TKT_price'] = $ticket_price;
1341
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1342
+				if ($TKT instanceof EE_Ticket) {
1343
+					// need to reset values to properly account for the date formats
1344
+					$TKT->set_date_format($incoming_date_formats[0]);
1345
+					$TKT->set_time_format($incoming_date_formats[1]);
1346
+					$TKT->set_timezone($evtobj->get_timezone());
1347
+					// set new values
1348
+					foreach ($TKT_values as $field => $value) {
1349
+						if ($field === 'TKT_qty') {
1350
+							$TKT->set_qty($value);
1351
+						} else {
1352
+							$TKT->set($field, $value);
1353
+						}
1354
+					}
1355
+					$update_prices = true;
1356
+				}
1357
+			}
1358
+			// cap ticket qty by datetime reg limits
1359
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1360
+			// update ticket.
1361
+			$TKT->save();
1362
+			// 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.
1363
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1364
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1365
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1366
+				$TKT->save();
1367
+			}
1368
+			// initially let's add the ticket to the dtt
1369
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1370
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1371
+			// add prices to ticket
1372
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1373
+		}
1374
+		// 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.
1375
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
1376
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1377
+		foreach ($tickets_removed as $id) {
1378
+			$id = absint($id);
1379
+			// get the ticket for this id
1380
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1381
+			// 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)
1382
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1383
+			foreach ($dtts as $dtt) {
1384
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1385
+			}
1386
+			// 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))
1387
+			$tkt_to_remove->delete_related_permanently('Price');
1388
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1389
+			$tkt_to_remove->delete_permanently();
1390
+		}
1391
+		return array($saved_dtt, $saved_tickets);
1392
+	}
1393
+
1394
+
1395
+	/**
1396
+	 * This attaches a list of given prices to a ticket.
1397
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1398
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1399
+	 * price info and prices are automatically "archived" via the ticket.
1400
+	 *
1401
+	 * @access  private
1402
+	 * @param array     $prices     Array of prices from the form.
1403
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1404
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1405
+	 * @return  void
1406
+	 * @throws EE_Error
1407
+	 * @throws InvalidArgumentException
1408
+	 * @throws InvalidDataTypeException
1409
+	 * @throws InvalidInterfaceException
1410
+	 * @throws ReflectionException
1411
+	 */
1412
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1413
+	{
1414
+		foreach ($prices as $row => $prc) {
1415
+			$PRC_values = array(
1416
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1417
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1418
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1419
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1420
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1421
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1422
+				'PRC_order'      => $row,
1423
+			);
1424
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1425
+				$PRC_values['PRC_ID'] = 0;
1426
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1427
+			} else {
1428
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1429
+				// update this price with new values
1430
+				foreach ($PRC_values as $field => $newprc) {
1431
+					$PRC->set($field, $newprc);
1432
+				}
1433
+				$PRC->save();
1434
+			}
1435
+			$ticket->_add_relation_to($PRC, 'Price');
1436
+		}
1437
+	}
1438
+
1439
+
1440
+	/**
1441
+	 * Add in our autosave ajax handlers
1442
+	 *
1443
+	 */
1444
+	protected function _ee_autosave_create_new()
1445
+	{
1446
+	}
1447
+
1448
+
1449
+	/**
1450
+	 * More autosave handlers.
1451
+	 */
1452
+	protected function _ee_autosave_edit()
1453
+	{
1454
+	}
1455
+
1456
+
1457
+	/**
1458
+	 *    _generate_publish_box_extra_content
1459
+	 *
1460
+	 * @throws DomainException
1461
+	 * @throws EE_Error
1462
+	 * @throws InvalidArgumentException
1463
+	 * @throws InvalidDataTypeException
1464
+	 * @throws InvalidInterfaceException
1465
+	 * @throws ReflectionException
1466
+	 */
1467
+	private function _generate_publish_box_extra_content()
1468
+	{
1469
+		// load formatter helper
1470
+		// args for getting related registrations
1471
+		$approved_query_args = array(
1472
+			array(
1473
+				'REG_deleted' => 0,
1474
+				'STS_ID'      => EEM_Registration::status_id_approved,
1475
+			),
1476
+		);
1477
+		$not_approved_query_args = array(
1478
+			array(
1479
+				'REG_deleted' => 0,
1480
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1481
+			),
1482
+		);
1483
+		$pending_payment_query_args = array(
1484
+			array(
1485
+				'REG_deleted' => 0,
1486
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1487
+			),
1488
+		);
1489
+		// publish box
1490
+		$publish_box_extra_args = array(
1491
+			'view_approved_reg_url'        => add_query_arg(
1492
+				array(
1493
+					'action'      => 'default',
1494
+					'event_id'    => $this->_cpt_model_obj->ID(),
1495
+					'_reg_status' => EEM_Registration::status_id_approved,
1496
+				),
1497
+				REG_ADMIN_URL
1498
+			),
1499
+			'view_not_approved_reg_url'    => add_query_arg(
1500
+				array(
1501
+					'action'      => 'default',
1502
+					'event_id'    => $this->_cpt_model_obj->ID(),
1503
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1504
+				),
1505
+				REG_ADMIN_URL
1506
+			),
1507
+			'view_pending_payment_reg_url' => add_query_arg(
1508
+				array(
1509
+					'action'      => 'default',
1510
+					'event_id'    => $this->_cpt_model_obj->ID(),
1511
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1512
+				),
1513
+				REG_ADMIN_URL
1514
+			),
1515
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1516
+				'Registration',
1517
+				$approved_query_args
1518
+			),
1519
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1520
+				'Registration',
1521
+				$not_approved_query_args
1522
+			),
1523
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1524
+				'Registration',
1525
+				$pending_payment_query_args
1526
+			),
1527
+			'misc_pub_section_class'       => apply_filters(
1528
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1529
+				'misc-pub-section'
1530
+			),
1531
+		);
1532
+		ob_start();
1533
+		do_action(
1534
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1535
+			$this->_cpt_model_obj
1536
+		);
1537
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1538
+		// load template
1539
+		EEH_Template::display_template(
1540
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1541
+			$publish_box_extra_args
1542
+		);
1543
+	}
1544
+
1545
+
1546
+	/**
1547
+	 * @return EE_Event
1548
+	 */
1549
+	public function get_event_object()
1550
+	{
1551
+		return $this->_cpt_model_obj;
1552
+	}
1553
+
1554
+
1555
+
1556
+
1557
+	/** METABOXES * */
1558
+	/**
1559
+	 * _register_event_editor_meta_boxes
1560
+	 * add all metaboxes related to the event_editor
1561
+	 *
1562
+	 * @return void
1563
+	 * @throws EE_Error
1564
+	 * @throws InvalidArgumentException
1565
+	 * @throws InvalidDataTypeException
1566
+	 * @throws InvalidInterfaceException
1567
+	 * @throws ReflectionException
1568
+	 */
1569
+	protected function _register_event_editor_meta_boxes()
1570
+	{
1571
+		$this->verify_cpt_object();
1572
+		if (EE_Registry::instance()->CFG->admin->useAdvancedEditor()) {
1573
+			add_action(
1574
+				'add_meta_boxes_espresso_events',
1575
+				function () {
1576
+					global $current_screen;
1577
+					remove_meta_box( 'authordiv' , $current_screen , 'normal' );
1578
+				},
1579
+				99
1580
+			);
1581
+			return;
1582
+		}
1583
+		add_meta_box(
1584
+			'espresso_event_editor_tickets',
1585
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1586
+			[$this, 'ticket_metabox'],
1587
+			$this->page_slug,
1588
+			'normal',
1589
+			'high'
1590
+		);
1591
+		add_meta_box(
1592
+			'espresso_event_editor_event_options',
1593
+			esc_html__('Event Registration Options', 'event_espresso'),
1594
+			array($this, 'registration_options_meta_box'),
1595
+			$this->page_slug,
1596
+			'side'
1597
+		);
1598
+		// NOTE: if you're looking for other metaboxes in here,
1599
+		// where a metabox has a related management page in the admin
1600
+		// you will find it setup in the related management page's "_Hooks" file.
1601
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1602
+	}
1603
+
1604
+
1605
+	/**
1606
+	 * @throws DomainException
1607
+	 * @throws EE_Error
1608
+	 * @throws InvalidArgumentException
1609
+	 * @throws InvalidDataTypeException
1610
+	 * @throws InvalidInterfaceException
1611
+	 * @throws ReflectionException
1612
+	 */
1613
+	public function ticket_metabox()
1614
+	{
1615
+		$existing_datetime_ids = $existing_ticket_ids = array();
1616
+		// defaults for template args
1617
+		$template_args = array(
1618
+			'existing_datetime_ids'    => '',
1619
+			'event_datetime_help_link' => '',
1620
+			'ticket_options_help_link' => '',
1621
+			'time'                     => null,
1622
+			'ticket_rows'              => '',
1623
+			'existing_ticket_ids'      => '',
1624
+			'total_ticket_rows'        => 1,
1625
+			'ticket_js_structure'      => '',
1626
+			'trash_icon'               => 'ee-lock-icon',
1627
+			'disabled'                 => '',
1628
+		);
1629
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1630
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1631
+		/**
1632
+		 * 1. Start with retrieving Datetimes
1633
+		 * 2. Fore each datetime get related tickets
1634
+		 * 3. For each ticket get related prices
1635
+		 */
1636
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1637
+		/** @type EE_Datetime $first_datetime */
1638
+		$first_datetime = reset($times);
1639
+		// do we get related tickets?
1640
+		if ($first_datetime instanceof EE_Datetime
1641
+			&& $first_datetime->ID() !== 0
1642
+		) {
1643
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1644
+			$template_args['time'] = $first_datetime;
1645
+			$related_tickets = $first_datetime->tickets(
1646
+				array(
1647
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1648
+					'default_where_conditions' => 'none',
1649
+				)
1650
+			);
1651
+			if (! empty($related_tickets)) {
1652
+				$template_args['total_ticket_rows'] = count($related_tickets);
1653
+				$row = 0;
1654
+				foreach ($related_tickets as $ticket) {
1655
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1656
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1657
+					$row++;
1658
+				}
1659
+			} else {
1660
+				$template_args['total_ticket_rows'] = 1;
1661
+				/** @type EE_Ticket $ticket */
1662
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1663
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1664
+			}
1665
+		} else {
1666
+			$template_args['time'] = $times[0];
1667
+			/** @type EE_Ticket $ticket */
1668
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1669
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1670
+			// NOTE: we're just sending the first default row
1671
+			// (decaf can't manage default tickets so this should be sufficient);
1672
+		}
1673
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1674
+			'event_editor_event_datetimes_help_tab'
1675
+		);
1676
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1677
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1678
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1679
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1680
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1681
+			true
1682
+		);
1683
+		$template = apply_filters(
1684
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1685
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1686
+		);
1687
+		EEH_Template::display_template($template, $template_args);
1688
+	}
1689
+
1690
+
1691
+	/**
1692
+	 * Setup an individual ticket form for the decaf event editor page
1693
+	 *
1694
+	 * @access private
1695
+	 * @param EE_Ticket $ticket   the ticket object
1696
+	 * @param boolean   $skeleton whether we're generating a skeleton for js manipulation
1697
+	 * @param int       $row
1698
+	 * @return string generated html for the ticket row.
1699
+	 * @throws DomainException
1700
+	 * @throws EE_Error
1701
+	 * @throws InvalidArgumentException
1702
+	 * @throws InvalidDataTypeException
1703
+	 * @throws InvalidInterfaceException
1704
+	 * @throws ReflectionException
1705
+	 */
1706
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1707
+	{
1708
+		$template_args = array(
1709
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1710
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1711
+				: '',
1712
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1713
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1714
+			'TKT_name'            => $ticket->get('TKT_name'),
1715
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1716
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1717
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1718
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1719
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1720
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1721
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1722
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1723
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1724
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1725
+				: ' disabled=disabled',
1726
+		);
1727
+		$price = $ticket->ID() !== 0
1728
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1729
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1730
+		$price_args = array(
1731
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1732
+			'PRC_amount'            => $price->get('PRC_amount'),
1733
+			'PRT_ID'                => $price->get('PRT_ID'),
1734
+			'PRC_ID'                => $price->get('PRC_ID'),
1735
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1736
+		);
1737
+		// make sure we have default start and end dates if skeleton
1738
+		// handle rows that should NOT be empty
1739
+		if (empty($template_args['TKT_start_date'])) {
1740
+			// if empty then the start date will be now.
1741
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1742
+		}
1743
+		if (empty($template_args['TKT_end_date'])) {
1744
+			// get the earliest datetime (if present);
1745
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1746
+				? $this->_cpt_model_obj->get_first_related(
1747
+					'Datetime',
1748
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1749
+				)
1750
+				: null;
1751
+			if (! empty($earliest_dtt)) {
1752
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1753
+			} else {
1754
+				$template_args['TKT_end_date'] = date(
1755
+					'Y-m-d h:i a',
1756
+					mktime(0, 0, 0, date('m'), date('d') + 7, date('Y'))
1757
+				);
1758
+			}
1759
+		}
1760
+		$template_args = array_merge($template_args, $price_args);
1761
+		$template = apply_filters(
1762
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1763
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1764
+			$ticket
1765
+		);
1766
+		return EEH_Template::display_template($template, $template_args, true);
1767
+	}
1768
+
1769
+
1770
+	/**
1771
+	 * @throws DomainException
1772
+	 * @throws EE_Error
1773
+	 */
1774
+	public function registration_options_meta_box()
1775
+	{
1776
+		$yes_no_values = array(
1777
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1778
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1779
+		);
1780
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1781
+			array(
1782
+				EEM_Registration::status_id_cancelled,
1783
+				EEM_Registration::status_id_declined,
1784
+				EEM_Registration::status_id_incomplete,
1785
+			),
1786
+			true
1787
+		);
1788
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1789
+		$template_args['_event'] = $this->_cpt_model_obj;
1790
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1791
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1792
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1793
+			'default_reg_status',
1794
+			$default_reg_status_values,
1795
+			$this->_cpt_model_obj->default_registration_status()
1796
+		);
1797
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1798
+			'display_desc',
1799
+			$yes_no_values,
1800
+			$this->_cpt_model_obj->display_description()
1801
+		);
1802
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1803
+			'display_ticket_selector',
1804
+			$yes_no_values,
1805
+			$this->_cpt_model_obj->display_ticket_selector(),
1806
+			'',
1807
+			'',
1808
+			false
1809
+		);
1810
+		$template_args['additional_registration_options'] = apply_filters(
1811
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1812
+			'',
1813
+			$template_args,
1814
+			$yes_no_values,
1815
+			$default_reg_status_values
1816
+		);
1817
+		EEH_Template::display_template(
1818
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1819
+			$template_args
1820
+		);
1821
+	}
1822
+
1823
+
1824
+	/**
1825
+	 * _get_events()
1826
+	 * This method simply returns all the events (for the given _view and paging)
1827
+	 *
1828
+	 * @access public
1829
+	 * @param int  $per_page     count of items per page (20 default);
1830
+	 * @param int  $current_page what is the current page being viewed.
1831
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1832
+	 *                           If FALSE then we return an array of event objects
1833
+	 *                           that match the given _view and paging parameters.
1834
+	 * @return array an array of event objects.
1835
+	 * @throws EE_Error
1836
+	 * @throws InvalidArgumentException
1837
+	 * @throws InvalidDataTypeException
1838
+	 * @throws InvalidInterfaceException
1839
+	 * @throws ReflectionException
1840
+	 * @throws Exception
1841
+	 * @throws Exception
1842
+	 * @throws Exception
1843
+	 */
1844
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1845
+	{
1846
+		$EEME = $this->_event_model();
1847
+		$offset = ($current_page - 1) * $per_page;
1848
+		$limit = $count ? null : $offset . ',' . $per_page;
1849
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1850
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1851
+		if (isset($this->_req_data['month_range'])) {
1852
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1853
+			// simulate the FIRST day of the month, that fixes issues for months like February
1854
+			// where PHP doesn't know what to assume for date.
1855
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1856
+			$month_r = ! empty($pieces[0]) ? date('m', EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1857
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1858
+		}
1859
+		$where = array();
1860
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1861
+		// determine what post_status our condition will have for the query.
1862
+		switch ($status) {
1863
+			case 'month':
1864
+			case 'today':
1865
+			case null:
1866
+			case 'all':
1867
+				break;
1868
+			case 'draft':
1869
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1870
+				break;
1871
+			default:
1872
+				$where['status'] = $status;
1873
+		}
1874
+		// categories?
1875
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1876
+			? $this->_req_data['EVT_CAT'] : null;
1877
+		if (! empty($category)) {
1878
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1879
+			$where['Term_Taxonomy.term_id'] = $category;
1880
+		}
1881
+		// date where conditions
1882
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1883
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1884
+			$DateTime = new DateTime(
1885
+				$year_r . '-' . $month_r . '-01 00:00:00',
1886
+				new DateTimeZone('UTC')
1887
+			);
1888
+			$start = $DateTime->getTimestamp();
1889
+			// set the datetime to be the end of the month
1890
+			$DateTime->setDate(
1891
+				$year_r,
1892
+				$month_r,
1893
+				$DateTime->format('t')
1894
+			)->setTime(23, 59, 59);
1895
+			$end = $DateTime->getTimestamp();
1896
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1897
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'today') {
1898
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1899
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1900
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1901
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1902
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] === 'month') {
1903
+			$now = date('Y-m-01');
1904
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1905
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1906
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1907
+							->setTime(23, 59, 59)
1908
+							->format(implode(' ', $start_formats));
1909
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1910
+		}
1911
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1912
+			$where['EVT_wp_user'] = get_current_user_id();
1913
+		} elseif (! isset($where['status'])
1914
+			&& ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1915
+		) {
1916
+			$where['OR'] = array(
1917
+				'status*restrict_private' => array('!=', 'private'),
1918
+				'AND'                     => array(
1919
+					'status*inclusive' => array('=', 'private'),
1920
+					'EVT_wp_user'      => get_current_user_id(),
1921
+				),
1922
+			);
1923
+		}
1924
+
1925
+		if (isset($this->_req_data['EVT_wp_user'])
1926
+			&& (int) $this->_req_data['EVT_wp_user'] !== (int) get_current_user_id()
1927
+			&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1928
+		) {
1929
+			$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1930
+		}
1931
+		// search query handling
1932
+		if (isset($this->_req_data['s'])) {
1933
+			$search_string = '%' . $this->_req_data['s'] . '%';
1934
+			$where['OR'] = array(
1935
+				'EVT_name'       => array('LIKE', $search_string),
1936
+				'EVT_desc'       => array('LIKE', $search_string),
1937
+				'EVT_short_desc' => array('LIKE', $search_string),
1938
+			);
1939
+		}
1940
+		// filter events by venue.
1941
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1942
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1943
+		}
1944
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1945
+		$query_params = apply_filters(
1946
+			'FHEE__Events_Admin_Page__get_events__query_params',
1947
+			array(
1948
+				$where,
1949
+				'limit'    => $limit,
1950
+				'order_by' => $orderby,
1951
+				'order'    => $order,
1952
+				'group_by' => 'EVT_ID',
1953
+			),
1954
+			$this->_req_data
1955
+		);
1956
+
1957
+		// let's first check if we have special requests coming in.
1958
+		if (isset($this->_req_data['active_status'])) {
1959
+			switch ($this->_req_data['active_status']) {
1960
+				case 'upcoming':
1961
+					return $EEME->get_upcoming_events($query_params, $count);
1962
+					break;
1963
+				case 'expired':
1964
+					return $EEME->get_expired_events($query_params, $count);
1965
+					break;
1966
+				case 'active':
1967
+					return $EEME->get_active_events($query_params, $count);
1968
+					break;
1969
+				case 'inactive':
1970
+					return $EEME->get_inactive_events($query_params, $count);
1971
+					break;
1972
+			}
1973
+		}
1974
+
1975
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1976
+		return $events;
1977
+	}
1978
+
1979
+
1980
+	/**
1981
+	 * handling for WordPress CPT actions (trash, restore, delete)
1982
+	 *
1983
+	 * @param string $post_id
1984
+	 * @throws EE_Error
1985
+	 * @throws InvalidArgumentException
1986
+	 * @throws InvalidDataTypeException
1987
+	 * @throws InvalidInterfaceException
1988
+	 * @throws ReflectionException
1989
+	 */
1990
+	public function trash_cpt_item($post_id)
1991
+	{
1992
+		$this->_req_data['EVT_ID'] = $post_id;
1993
+		$this->_trash_or_restore_event('trash', false);
1994
+	}
1995
+
1996
+
1997
+	/**
1998
+	 * @param string $post_id
1999
+	 * @throws EE_Error
2000
+	 * @throws InvalidArgumentException
2001
+	 * @throws InvalidDataTypeException
2002
+	 * @throws InvalidInterfaceException
2003
+	 * @throws ReflectionException
2004
+	 */
2005
+	public function restore_cpt_item($post_id)
2006
+	{
2007
+		$this->_req_data['EVT_ID'] = $post_id;
2008
+		$this->_trash_or_restore_event('draft', false);
2009
+	}
2010
+
2011
+
2012
+	/**
2013
+	 * @param string $post_id
2014
+	 * @throws EE_Error
2015
+	 * @throws InvalidArgumentException
2016
+	 * @throws InvalidDataTypeException
2017
+	 * @throws InvalidInterfaceException
2018
+	 * @throws ReflectionException
2019
+	 */
2020
+	public function delete_cpt_item($post_id)
2021
+	{
2022
+		$this->_req_data['EVT_ID'] = $post_id;
2023
+		$this->_delete_event(false);
2024
+	}
2025
+
2026
+
2027
+	/**
2028
+	 * _trash_or_restore_event
2029
+	 *
2030
+	 * @access protected
2031
+	 * @param string $event_status
2032
+	 * @param bool   $redirect_after
2033
+	 * @throws EE_Error
2034
+	 * @throws InvalidArgumentException
2035
+	 * @throws InvalidDataTypeException
2036
+	 * @throws InvalidInterfaceException
2037
+	 * @throws ReflectionException
2038
+	 */
2039
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
2040
+	{
2041
+		// determine the event id and set to array.
2042
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
2043
+		// loop thru events
2044
+		if ($EVT_ID) {
2045
+			// clean status
2046
+			$event_status = sanitize_key($event_status);
2047
+			// grab status
2048
+			if (! empty($event_status)) {
2049
+				$success = $this->_change_event_status($EVT_ID, $event_status);
2050
+			} else {
2051
+				$success = false;
2052
+				$msg = esc_html__(
2053
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2054
+					'event_espresso'
2055
+				);
2056
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2057
+			}
2058
+		} else {
2059
+			$success = false;
2060
+			$msg = esc_html__(
2061
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
2062
+				'event_espresso'
2063
+			);
2064
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2065
+		}
2066
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2067
+		if ($redirect_after) {
2068
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
2069
+		}
2070
+	}
2071
+
2072
+
2073
+	/**
2074
+	 * _trash_or_restore_events
2075
+	 *
2076
+	 * @access protected
2077
+	 * @param string $event_status
2078
+	 * @return void
2079
+	 * @throws EE_Error
2080
+	 * @throws InvalidArgumentException
2081
+	 * @throws InvalidDataTypeException
2082
+	 * @throws InvalidInterfaceException
2083
+	 * @throws ReflectionException
2084
+	 */
2085
+	protected function _trash_or_restore_events($event_status = 'trash')
2086
+	{
2087
+		// clean status
2088
+		$event_status = sanitize_key($event_status);
2089
+		// grab status
2090
+		if (! empty($event_status)) {
2091
+			$success = true;
2092
+			// determine the event id and set to array.
2093
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2094
+			// loop thru events
2095
+			foreach ($EVT_IDs as $EVT_ID) {
2096
+				if ($EVT_ID = absint($EVT_ID)) {
2097
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2098
+					$success = $results !== false ? $success : false;
2099
+				} else {
2100
+					$msg = sprintf(
2101
+						esc_html__(
2102
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2103
+							'event_espresso'
2104
+						),
2105
+						$EVT_ID
2106
+					);
2107
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2108
+					$success = false;
2109
+				}
2110
+			}
2111
+		} else {
2112
+			$success = false;
2113
+			$msg = esc_html__(
2114
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2115
+				'event_espresso'
2116
+			);
2117
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2118
+		}
2119
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2120
+		$success = $success ? 2 : false;
2121
+		$action = $event_status === 'trash' ? 'moved to the trash' : 'restored from the trash';
2122
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2123
+	}
2124
+
2125
+
2126
+	/**
2127
+	 * _trash_or_restore_events
2128
+	 *
2129
+	 * @access  private
2130
+	 * @param int    $EVT_ID
2131
+	 * @param string $event_status
2132
+	 * @return bool
2133
+	 * @throws EE_Error
2134
+	 * @throws InvalidArgumentException
2135
+	 * @throws InvalidDataTypeException
2136
+	 * @throws InvalidInterfaceException
2137
+	 * @throws ReflectionException
2138
+	 */
2139
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2140
+	{
2141
+		// grab event id
2142
+		if (! $EVT_ID) {
2143
+			$msg = esc_html__(
2144
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2145
+				'event_espresso'
2146
+			);
2147
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2148
+			return false;
2149
+		}
2150
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2151
+		// clean status
2152
+		$event_status = sanitize_key($event_status);
2153
+		// grab status
2154
+		if (empty($event_status)) {
2155
+			$msg = esc_html__(
2156
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2157
+				'event_espresso'
2158
+			);
2159
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2160
+			return false;
2161
+		}
2162
+		// was event trashed or restored ?
2163
+		switch ($event_status) {
2164
+			case 'draft':
2165
+				$action = 'restored from the trash';
2166
+				$hook = 'AHEE_event_restored_from_trash';
2167
+				break;
2168
+			case 'trash':
2169
+				$action = 'moved to the trash';
2170
+				$hook = 'AHEE_event_moved_to_trash';
2171
+				break;
2172
+			default:
2173
+				$action = 'updated';
2174
+				$hook = false;
2175
+		}
2176
+		// use class to change status
2177
+		$this->_cpt_model_obj->set_status($event_status);
2178
+		$success = $this->_cpt_model_obj->save();
2179
+		if ($success === false) {
2180
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2181
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2182
+			return false;
2183
+		}
2184
+		if ($hook) {
2185
+			do_action($hook);
2186
+		}
2187
+		return true;
2188
+	}
2189
+
2190
+
2191
+	/**
2192
+	 * _delete_event
2193
+	 *
2194
+	 * @access protected
2195
+	 * @param bool $redirect_after
2196
+	 * @throws EE_Error
2197
+	 * @throws InvalidArgumentException
2198
+	 * @throws InvalidDataTypeException
2199
+	 * @throws InvalidInterfaceException
2200
+	 * @throws ReflectionException
2201
+	 */
2202
+	protected function _delete_event($redirect_after = true)
2203
+	{
2204
+		// determine the event id and set to array.
2205
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : null;
2206
+		$EVT_ID = isset($this->_req_data['post']) ? absint($this->_req_data['post']) : $EVT_ID;
2207
+		// loop thru events
2208
+		if ($EVT_ID) {
2209
+			$success = $this->_permanently_delete_event($EVT_ID);
2210
+			// get list of events with no prices
2211
+			$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2212
+			// remove this event from the list of events with no prices
2213
+			if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2214
+				unset($espresso_no_ticket_prices[ $EVT_ID ]);
2215
+			}
2216
+			update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2217
+		} else {
2218
+			$success = false;
2219
+			$msg = esc_html__(
2220
+				'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2221
+				'event_espresso'
2222
+			);
2223
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2224
+		}
2225
+		if ($redirect_after) {
2226
+			$this->_redirect_after_action(
2227
+				$success,
2228
+				'Event',
2229
+				'deleted',
2230
+				array('action' => 'default', 'status' => 'trash')
2231
+			);
2232
+		}
2233
+	}
2234
+
2235
+
2236
+	/**
2237
+	 * _delete_events
2238
+	 *
2239
+	 * @access protected
2240
+	 * @return void
2241
+	 * @throws EE_Error
2242
+	 * @throws InvalidArgumentException
2243
+	 * @throws InvalidDataTypeException
2244
+	 * @throws InvalidInterfaceException
2245
+	 * @throws ReflectionException
2246
+	 */
2247
+	protected function _delete_events()
2248
+	{
2249
+		$success = true;
2250
+		// get list of events with no prices
2251
+		$espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2252
+		// determine the event id and set to array.
2253
+		$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2254
+		// loop thru events
2255
+		foreach ($EVT_IDs as $EVT_ID) {
2256
+			$EVT_ID = absint($EVT_ID);
2257
+			if ($EVT_ID) {
2258
+				$results = $this->_permanently_delete_event($EVT_ID);
2259
+				$success = $results !== false ? $success : false;
2260
+				// remove this event from the list of events with no prices
2261
+				unset($espresso_no_ticket_prices[ $EVT_ID ]);
2262
+			} else {
2263
+				$success = false;
2264
+				$msg = esc_html__(
2265
+					'An error occurred. An event could not be deleted because a valid event ID was not not supplied.',
2266
+					'event_espresso'
2267
+				);
2268
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2269
+			}
2270
+		}
2271
+		update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2272
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2273
+		$success = $success ? 2 : false;
2274
+		$this->_redirect_after_action($success, 'Events', 'deleted', array('action' => 'default'));
2275
+	}
2276
+
2277
+
2278
+	/**
2279
+	 * _permanently_delete_event
2280
+	 *
2281
+	 * @access  private
2282
+	 * @param int $EVT_ID
2283
+	 * @return bool
2284
+	 * @throws EE_Error
2285
+	 * @throws InvalidArgumentException
2286
+	 * @throws InvalidDataTypeException
2287
+	 * @throws InvalidInterfaceException
2288
+	 * @throws ReflectionException
2289
+	 */
2290
+	private function _permanently_delete_event($EVT_ID = 0)
2291
+	{
2292
+		// grab event id
2293
+		if (! $EVT_ID) {
2294
+			$msg = esc_html__(
2295
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2296
+				'event_espresso'
2297
+			);
2298
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2299
+			return false;
2300
+		}
2301
+		if (! $this->_cpt_model_obj instanceof EE_Event
2302
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2303
+		) {
2304
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2305
+		}
2306
+		if (! $this->_cpt_model_obj instanceof EE_Event) {
2307
+			return false;
2308
+		}
2309
+		// need to delete related tickets and prices first.
2310
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2311
+		foreach ($datetimes as $datetime) {
2312
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2313
+			$tickets = $datetime->get_many_related('Ticket');
2314
+			foreach ($tickets as $ticket) {
2315
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2316
+				$ticket->delete_related_permanently('Price');
2317
+				$ticket->delete_permanently();
2318
+			}
2319
+			$datetime->delete();
2320
+		}
2321
+		// what about related venues or terms?
2322
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2323
+		foreach ($venues as $venue) {
2324
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2325
+		}
2326
+		// any attached question groups?
2327
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2328
+		if (! empty($question_groups)) {
2329
+			foreach ($question_groups as $question_group) {
2330
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2331
+			}
2332
+		}
2333
+		// Message Template Groups
2334
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2335
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2336
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2337
+		foreach ($term_taxonomies as $term_taxonomy) {
2338
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2339
+		}
2340
+		$success = $this->_cpt_model_obj->delete_permanently();
2341
+		// did it all go as planned ?
2342
+		if ($success) {
2343
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2344
+			EE_Error::add_success($msg);
2345
+		} else {
2346
+			$msg = sprintf(
2347
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2348
+				$EVT_ID
2349
+			);
2350
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2351
+			return false;
2352
+		}
2353
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2354
+		return true;
2355
+	}
2356
+
2357
+
2358
+	/**
2359
+	 * get total number of events
2360
+	 *
2361
+	 * @access public
2362
+	 * @return int
2363
+	 * @throws EE_Error
2364
+	 * @throws InvalidArgumentException
2365
+	 * @throws InvalidDataTypeException
2366
+	 * @throws InvalidInterfaceException
2367
+	 */
2368
+	public function total_events()
2369
+	{
2370
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2371
+		return $count;
2372
+	}
2373
+
2374
+
2375
+	/**
2376
+	 * get total number of draft events
2377
+	 *
2378
+	 * @access public
2379
+	 * @return int
2380
+	 * @throws EE_Error
2381
+	 * @throws InvalidArgumentException
2382
+	 * @throws InvalidDataTypeException
2383
+	 * @throws InvalidInterfaceException
2384
+	 */
2385
+	public function total_events_draft()
2386
+	{
2387
+		$where = array(
2388
+			'status' => array('IN', array('draft', 'auto-draft')),
2389
+		);
2390
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2391
+		return $count;
2392
+	}
2393
+
2394
+
2395
+	/**
2396
+	 * get total number of trashed events
2397
+	 *
2398
+	 * @access public
2399
+	 * @return int
2400
+	 * @throws EE_Error
2401
+	 * @throws InvalidArgumentException
2402
+	 * @throws InvalidDataTypeException
2403
+	 * @throws InvalidInterfaceException
2404
+	 */
2405
+	public function total_trashed_events()
2406
+	{
2407
+		$where = array(
2408
+			'status' => 'trash',
2409
+		);
2410
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2411
+		return $count;
2412
+	}
2413
+
2414
+
2415
+	/**
2416
+	 *    _default_event_settings
2417
+	 *    This generates the Default Settings Tab
2418
+	 *
2419
+	 * @return void
2420
+	 * @throws DomainException
2421
+	 * @throws EE_Error
2422
+	 * @throws InvalidArgumentException
2423
+	 * @throws InvalidDataTypeException
2424
+	 * @throws InvalidInterfaceException
2425
+	 */
2426
+	protected function _default_event_settings()
2427
+	{
2428
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2429
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2430
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2431
+		$this->display_admin_page_with_sidebar();
2432
+	}
2433
+
2434
+
2435
+	/**
2436
+	 * Return the form for event settings.
2437
+	 *
2438
+	 * @return EE_Form_Section_Proper
2439
+	 * @throws EE_Error
2440
+	 */
2441
+	protected function _default_event_settings_form()
2442
+	{
2443
+		$registration_config = EE_Registry::instance()->CFG->registration;
2444
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2445
+			// exclude
2446
+			array(
2447
+				EEM_Registration::status_id_cancelled,
2448
+				EEM_Registration::status_id_declined,
2449
+				EEM_Registration::status_id_incomplete,
2450
+				EEM_Registration::status_id_wait_list,
2451
+			),
2452
+			true
2453
+		);
2454
+		return new EE_Form_Section_Proper(
2455
+			array(
2456
+				'name'            => 'update_default_event_settings',
2457
+				'html_id'         => 'update_default_event_settings',
2458
+				'html_class'      => 'form-table',
2459
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2460
+				'subsections'     => apply_filters(
2461
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2462
+					array(
2463
+						'default_reg_status'  => new EE_Select_Input(
2464
+							$registration_stati_for_selection,
2465
+							array(
2466
+								'default'         => isset($registration_config->default_STS_ID)
2467
+													 && array_key_exists(
2468
+														 $registration_config->default_STS_ID,
2469
+														 $registration_stati_for_selection
2470
+													 )
2471
+									? sanitize_text_field($registration_config->default_STS_ID)
2472
+									: EEM_Registration::status_id_pending_payment,
2473
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2474
+													 . EEH_Template::get_help_tab_link(
2475
+														 'default_settings_status_help_tab'
2476
+													 ),
2477
+								'html_help_text'  => esc_html__(
2478
+									'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.',
2479
+									'event_espresso'
2480
+								),
2481
+							)
2482
+						),
2483
+						'default_max_tickets' => new EE_Integer_Input(
2484
+							array(
2485
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2486
+									? $registration_config->default_maximum_number_of_tickets
2487
+									: EEM_Event::get_default_additional_limit(),
2488
+								'html_label_text' => esc_html__(
2489
+									'Default Maximum Tickets Allowed Per Order:',
2490
+									'event_espresso'
2491
+								)
2492
+													 . EEH_Template::get_help_tab_link(
2493
+														 'default_maximum_tickets_help_tab"'
2494
+													 ),
2495
+								'html_help_text'  => esc_html__(
2496
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2497
+									'event_espresso'
2498
+								),
2499
+							)
2500
+						),
2501
+					)
2502
+				),
2503
+			)
2504
+		);
2505
+	}
2506
+
2507
+
2508
+	/**
2509
+	 * @return void
2510
+	 * @throws EE_Error
2511
+	 * @throws InvalidArgumentException
2512
+	 * @throws InvalidDataTypeException
2513
+	 * @throws InvalidInterfaceException
2514
+	 */
2515
+	protected function _update_default_event_settings()
2516
+	{
2517
+		$form = $this->_default_event_settings_form();
2518
+		if ($form->was_submitted()) {
2519
+			$form->receive_form_submission();
2520
+			if ($form->is_valid()) {
2521
+				$registration_config = EE_Registry::instance()->CFG->registration;
2522
+				$valid_data = $form->valid_data();
2523
+				if (isset($valid_data['default_reg_status'])) {
2524
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2525
+				}
2526
+				if (isset($valid_data['default_max_tickets'])) {
2527
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2528
+				}
2529
+				do_action(
2530
+					'AHEE__Events_Admin_Page___update_default_event_settings',
2531
+					$valid_data,
2532
+					EE_Registry::instance()->CFG,
2533
+					$this
2534
+				);
2535
+				// update because data was valid!
2536
+				EE_Registry::instance()->CFG->update_espresso_config();
2537
+				EE_Error::overwrite_success();
2538
+				EE_Error::add_success(
2539
+					__('Default Event Settings were updated', 'event_espresso')
2540
+				);
2541
+			}
2542
+		}
2543
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2544
+	}
2545
+
2546
+
2547
+	/*************        Templates        *************/
2548
+	protected function _template_settings()
2549
+	{
2550
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2551
+		$this->_template_args['preview_img'] = '<img src="'
2552
+											   . EVENTS_ASSETS_URL
2553
+											   . '/images/'
2554
+											   . 'caffeinated_template_features.jpg" alt="'
2555
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2556
+											   . '" />';
2557
+		$this->_template_args['preview_text'] = '<strong>'
2558
+												. esc_html__(
2559
+													'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.',
2560
+													'event_espresso'
2561
+												) . '</strong>';
2562
+		$this->display_admin_caf_preview_page('template_settings_tab');
2563
+	}
2564
+
2565
+
2566
+	/** Event Category Stuff **/
2567
+	/**
2568
+	 * set the _category property with the category object for the loaded page.
2569
+	 *
2570
+	 * @access private
2571
+	 * @return void
2572
+	 */
2573
+	private function _set_category_object()
2574
+	{
2575
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2576
+			return;
2577
+		} //already have the category object so get out.
2578
+		// set default category object
2579
+		$this->_set_empty_category_object();
2580
+		// only set if we've got an id
2581
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2582
+			return;
2583
+		}
2584
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2585
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2586
+		if (! empty($term)) {
2587
+			$this->_category->category_name = $term->name;
2588
+			$this->_category->category_identifier = $term->slug;
2589
+			$this->_category->category_desc = $term->description;
2590
+			$this->_category->id = $term->term_id;
2591
+			$this->_category->parent = $term->parent;
2592
+		}
2593
+	}
2594
+
2595
+
2596
+	/**
2597
+	 * Clears out category properties.
2598
+	 */
2599
+	private function _set_empty_category_object()
2600
+	{
2601
+		$this->_category = new stdClass();
2602
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2603
+		$this->_category->id = $this->_category->parent = 0;
2604
+	}
2605
+
2606
+
2607
+	/**
2608
+	 * @throws DomainException
2609
+	 * @throws EE_Error
2610
+	 * @throws InvalidArgumentException
2611
+	 * @throws InvalidDataTypeException
2612
+	 * @throws InvalidInterfaceException
2613
+	 */
2614
+	protected function _category_list_table()
2615
+	{
2616
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2617
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2618
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2619
+			'add_category',
2620
+			'add_category',
2621
+			array(),
2622
+			'add-new-h2'
2623
+		);
2624
+		$this->display_admin_list_table_page_with_sidebar();
2625
+	}
2626
+
2627
+
2628
+	/**
2629
+	 * Output category details view.
2630
+	 *
2631
+	 * @param string $view
2632
+	 * @throws DomainException
2633
+	 * @throws EE_Error
2634
+	 * @throws InvalidArgumentException
2635
+	 * @throws InvalidDataTypeException
2636
+	 * @throws InvalidInterfaceException
2637
+	 */
2638
+	protected function _category_details($view)
2639
+	{
2640
+		// load formatter helper
2641
+		// load field generator helper
2642
+		$route = $view === 'edit' ? 'update_category' : 'insert_category';
2643
+		$this->_set_add_edit_form_tags($route);
2644
+		$this->_set_category_object();
2645
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2646
+		$delete_action = 'delete_category';
2647
+		// custom redirect
2648
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2649
+			array('action' => 'category_list'),
2650
+			$this->_admin_base_url
2651
+		);
2652
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2653
+		// take care of contents
2654
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2655
+		$this->display_admin_page_with_sidebar();
2656
+	}
2657
+
2658
+
2659
+	/**
2660
+	 * Output category details content.
2661
+	 *
2662
+	 * @throws DomainException
2663
+	 */
2664
+	protected function _category_details_content()
2665
+	{
2666
+		$editor_args['category_desc'] = array(
2667
+			'type'          => 'wp_editor',
2668
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2669
+			'class'         => 'my_editor_custom',
2670
+			'wpeditor_args' => array('media_buttons' => false),
2671
+		);
2672
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2673
+		$all_terms = get_terms(
2674
+			array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2675
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2676
+		);
2677
+		// setup category select for term parents.
2678
+		$category_select_values[] = array(
2679
+			'text' => esc_html__('No Parent', 'event_espresso'),
2680
+			'id'   => 0,
2681
+		);
2682
+		foreach ($all_terms as $term) {
2683
+			$category_select_values[] = array(
2684
+				'text' => $term->name,
2685
+				'id'   => $term->term_id,
2686
+			);
2687
+		}
2688
+		$category_select = EEH_Form_Fields::select_input(
2689
+			'category_parent',
2690
+			$category_select_values,
2691
+			$this->_category->parent
2692
+		);
2693
+		$template_args = array(
2694
+			'category'                 => $this->_category,
2695
+			'category_select'          => $category_select,
2696
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2697
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2698
+			'disable'                  => '',
2699
+			'disabled_message'         => false,
2700
+		);
2701
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2702
+		return EEH_Template::display_template($template, $template_args, true);
2703
+	}
2704
+
2705
+
2706
+	/**
2707
+	 * Handles deleting categories.
2708
+	 */
2709
+	protected function _delete_categories()
2710
+	{
2711
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2712
+			: (array) $this->_req_data['category_id'];
2713
+		foreach ($cat_ids as $cat_id) {
2714
+			$this->_delete_category($cat_id);
2715
+		}
2716
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2717
+		$query_args = array(
2718
+			'action' => 'category_list',
2719
+		);
2720
+		$this->_redirect_after_action(0, '', '', $query_args);
2721
+	}
2722
+
2723
+
2724
+	/**
2725
+	 * Handles deleting specific category.
2726
+	 *
2727
+	 * @param int $cat_id
2728
+	 */
2729
+	protected function _delete_category($cat_id)
2730
+	{
2731
+		$cat_id = absint($cat_id);
2732
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2733
+	}
2734
+
2735
+
2736
+	/**
2737
+	 * Handles triggering the update or insertion of a new category.
2738
+	 *
2739
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2740
+	 * @throws EE_Error
2741
+	 * @throws InvalidArgumentException
2742
+	 * @throws InvalidDataTypeException
2743
+	 * @throws InvalidInterfaceException
2744
+	 */
2745
+	protected function _insert_or_update_category($new_category)
2746
+	{
2747
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2748
+		$success = 0; // we already have a success message so lets not send another.
2749
+		if ($cat_id) {
2750
+			$query_args = array(
2751
+				'action'     => 'edit_category',
2752
+				'EVT_CAT_ID' => $cat_id,
2753
+			);
2754
+		} else {
2755
+			$query_args = array('action' => 'add_category');
2756
+		}
2757
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2758
+	}
2759
+
2760
+
2761
+	/**
2762
+	 * Inserts or updates category
2763
+	 *
2764
+	 * @param bool $update (true indicates we're updating a category).
2765
+	 * @return bool|mixed|string
2766
+	 */
2767
+	private function _insert_category($update = false)
2768
+	{
2769
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2770
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2771
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2772
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2773
+		if (empty($category_name)) {
2774
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2775
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2776
+			return false;
2777
+		}
2778
+		$term_args = array(
2779
+			'name'        => $category_name,
2780
+			'description' => $category_desc,
2781
+			'parent'      => $category_parent,
2782
+		);
2783
+		// was the category_identifier input disabled?
2784
+		if (isset($this->_req_data['category_identifier'])) {
2785
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2786
+		}
2787
+		$insert_ids = $update
2788
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2789
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2790
+		if (! is_array($insert_ids)) {
2791
+			$msg = esc_html__(
2792
+				'An error occurred and the category has not been saved to the database.',
2793
+				'event_espresso'
2794
+			);
2795
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2796
+		} else {
2797
+			$cat_id = $insert_ids['term_id'];
2798
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2799
+			EE_Error::add_success($msg);
2800
+		}
2801
+		return $cat_id;
2802
+	}
2803
+
2804
+
2805
+	/**
2806
+	 * Gets categories or count of categories matching the arguments in the request.
2807
+	 *
2808
+	 * @param int  $per_page
2809
+	 * @param int  $current_page
2810
+	 * @param bool $count
2811
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2812
+	 * @throws EE_Error
2813
+	 * @throws InvalidArgumentException
2814
+	 * @throws InvalidDataTypeException
2815
+	 * @throws InvalidInterfaceException
2816
+	 */
2817
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2818
+	{
2819
+		// testing term stuff
2820
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2821
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2822
+		$limit = ($current_page - 1) * $per_page;
2823
+		$where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2824
+		if (isset($this->_req_data['s'])) {
2825
+			$sstr = '%' . $this->_req_data['s'] . '%';
2826
+			$where['OR'] = array(
2827
+				'Term.name'   => array('LIKE', $sstr),
2828
+				'description' => array('LIKE', $sstr),
2829
+			);
2830
+		}
2831
+		$query_params = array(
2832
+			$where,
2833
+			'order_by'   => array($orderby => $order),
2834
+			'limit'      => $limit . ',' . $per_page,
2835
+			'force_join' => array('Term'),
2836
+		);
2837
+		$categories = $count
2838
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2839
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2840
+		return $categories;
2841
+	}
2842
+
2843
+	/* end category stuff */
2844
+	/**************/
2845
+
2846
+
2847
+	/**
2848
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2849
+	 *
2850
+	 * @throws EE_Error
2851
+	 * @throws InvalidArgumentException
2852
+	 * @throws InvalidDataTypeException
2853
+	 * @throws InvalidInterfaceException
2854
+	 */
2855
+	public function save_timezonestring_setting()
2856
+	{
2857
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2858
+			? $this->_req_data['timezone_selected']
2859
+			: '';
2860
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2861
+			EE_Error::add_error(
2862
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2863
+				__FILE__,
2864
+				__FUNCTION__,
2865
+				__LINE__
2866
+			);
2867
+			$this->_template_args['error'] = true;
2868
+			$this->_return_json();
2869
+		}
2870
+
2871
+		update_option('timezone_string', $timezone_string);
2872
+		EE_Error::add_success(
2873
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2874
+		);
2875
+		$this->_template_args['success'] = true;
2876
+		$this->_return_json(true, array('action' => 'create_new'));
2877
+	}
2878 2878
 }
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,11 +561,11 @@  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
             array(),
566 566
             EVENT_ESPRESSO_VERSION
567 567
         );
568
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
568
+        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL.'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
569 569
         wp_enqueue_style('events-admin-css');
570 570
         wp_enqueue_style('ee-cat-admin');
571 571
         // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
@@ -573,7 +573,7 @@  discard block
 block discarded – undo
573 573
         // scripts
574 574
         wp_register_script(
575 575
             'event_editor_js',
576
-            EVENTS_ASSETS_URL . 'event_editor.js',
576
+            EVENTS_ASSETS_URL.'event_editor.js',
577 577
             array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
578 578
             EVENT_ESPRESSO_VERSION,
579 579
             true
@@ -599,7 +599,7 @@  discard block
 block discarded – undo
599 599
         wp_enqueue_style('espresso-ui-theme');
600 600
         wp_register_style(
601 601
             'event-editor-css',
602
-            EVENTS_ASSETS_URL . 'event-editor.css',
602
+            EVENTS_ASSETS_URL.'event-editor.css',
603 603
             array('ee-admin-css'),
604 604
             EVENT_ESPRESSO_VERSION
605 605
         );
@@ -607,7 +607,7 @@  discard block
 block discarded – undo
607 607
         // scripts
608 608
         wp_register_script(
609 609
             'event-datetime-metabox',
610
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
610
+            EVENTS_ASSETS_URL.'event-datetime-metabox.js',
611 611
             array('event_editor_js', 'ee-datepicker'),
612 612
             EVENT_ESPRESSO_VERSION
613 613
         );
@@ -676,15 +676,15 @@  discard block
 block discarded – undo
676 676
     public function verify_event_edit($event = null, $req_type = '')
677 677
     {
678 678
         // don't need to do this when processing
679
-        if (! empty($req_type)) {
679
+        if ( ! empty($req_type)) {
680 680
             return;
681 681
         }
682 682
         // no event?
683
-        if (! $event instanceof EE_Event) {
683
+        if ( ! $event instanceof EE_Event) {
684 684
             $event = $this->_cpt_model_obj;
685 685
         }
686 686
         // STILL no event?
687
-        if (! $event instanceof EE_Event) {
687
+        if ( ! $event instanceof EE_Event) {
688 688
             return;
689 689
         }
690 690
         $orig_status = $event->status();
@@ -723,7 +723,7 @@  discard block
 block discarded – undo
723 723
             );
724 724
         }
725 725
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
726
-        if (! $event->tickets_on_sale()) {
726
+        if ( ! $event->tickets_on_sale()) {
727 727
             return;
728 728
         }
729 729
         // made it here so show warning
@@ -771,7 +771,7 @@  discard block
 block discarded – undo
771 771
     {
772 772
         $has_timezone_string = get_option('timezone_string');
773 773
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
774
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
774
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
775 775
             EE_Error::add_attention(
776 776
                 sprintf(
777 777
                     __(
@@ -855,31 +855,31 @@  discard block
 block discarded – undo
855 855
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
856 856
         $statuses = array(
857 857
             'sold_out_status'  => array(
858
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
858
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
859 859
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
860 860
             ),
861 861
             'active_status'    => array(
862
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
862
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
863 863
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
864 864
             ),
865 865
             'upcoming_status'  => array(
866
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
866
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
867 867
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
868 868
             ),
869 869
             'postponed_status' => array(
870
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
870
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
871 871
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
872 872
             ),
873 873
             'cancelled_status' => array(
874
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
874
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
875 875
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
876 876
             ),
877 877
             'expired_status'   => array(
878
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
878
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
879 879
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
880 880
             ),
881 881
             'inactive_status'  => array(
882
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
882
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
883 883
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
884 884
             ),
885 885
         );
@@ -898,7 +898,7 @@  discard block
 block discarded – undo
898 898
      */
899 899
     private function _event_model()
900 900
     {
901
-        if (! $this->_event_model instanceof EEM_Event) {
901
+        if ( ! $this->_event_model instanceof EEM_Event) {
902 902
             $this->_event_model = EE_Registry::instance()->load_model('Event');
903 903
         }
904 904
         return $this->_event_model;
@@ -918,7 +918,7 @@  discard block
 block discarded – undo
918 918
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
919 919
     {
920 920
         // make sure this is only when editing
921
-        if (! empty($id)) {
921
+        if ( ! empty($id)) {
922 922
             $post = get_post($id);
923 923
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
924 924
                        . esc_html__('Shortcode', 'event_espresso')
@@ -956,7 +956,7 @@  discard block
 block discarded – undo
956 956
                     'button'
957 957
                 );
958 958
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
959
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
959
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
960 960
             'create_new',
961 961
             'add',
962 962
             array(),
@@ -1116,7 +1116,7 @@  discard block
 block discarded – undo
1116 1116
      */
1117 1117
     protected function _default_venue_update(EE_Event $evtobj, $data)
1118 1118
     {
1119
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1119
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1120 1120
         $venue_model = EE_Registry::instance()->load_model('Venue');
1121 1121
         $rows_affected = null;
1122 1122
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1147,7 +1147,7 @@  discard block
 block discarded – undo
1147 1147
             'status'              => 'publish',
1148 1148
         );
1149 1149
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1150
-        if (! empty($venue_id)) {
1150
+        if ( ! empty($venue_id)) {
1151 1151
             $update_where = array($venue_model->primary_key_name() => $venue_id);
1152 1152
             $rows_affected = $venue_model->update($venue_array, array($update_where));
1153 1153
             // 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.
@@ -1197,7 +1197,7 @@  discard block
 block discarded – undo
1197 1197
                 'DTT_order'     => $row,
1198 1198
             );
1199 1199
             // 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.
1200
-            if (! empty($dtt['DTT_ID'])) {
1200
+            if ( ! empty($dtt['DTT_ID'])) {
1201 1201
                 $DTM = EE_Registry::instance()
1202 1202
                                   ->load_model('Datetime', array($evtobj->get_timezone()))
1203 1203
                                   ->get_one_by_ID($dtt['DTT_ID']);
@@ -1207,7 +1207,7 @@  discard block
 block discarded – undo
1207 1207
                     $DTM->set($field, $value);
1208 1208
                 }
1209 1209
                 // 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.
1210
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1210
+                $saved_dtts[$DTM->ID()] = $DTM;
1211 1211
             } else {
1212 1212
                 $DTM = EE_Registry::instance()->load_class(
1213 1213
                     'Datetime',
@@ -1240,14 +1240,14 @@  discard block
 block discarded – undo
1240 1240
         foreach ($data['edit_tickets'] as $row => $tkt) {
1241 1241
             $incoming_date_formats = array('Y-m-d', 'h:i a');
1242 1242
             $update_prices = false;
1243
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1244
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1243
+            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1244
+                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1245 1245
             // trim inputs to ensure any excess whitespace is removed.
1246 1246
             $tkt = array_map('trim', $tkt);
1247 1247
             if (empty($tkt['TKT_start_date'])) {
1248 1248
                 // let's use now in the set timezone.
1249 1249
                 $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1250
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1250
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1251 1251
             }
1252 1252
             if (empty($tkt['TKT_end_date'])) {
1253 1253
                 // use the start date of the first datetime
@@ -1282,7 +1282,7 @@  discard block
 block discarded – undo
1282 1282
             // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1283 1283
             // 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.
1284 1284
             // 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.
1285
-            if (! empty($tkt['TKT_ID'])) {
1285
+            if ( ! empty($tkt['TKT_ID'])) {
1286 1286
                 $TKT = EE_Registry::instance()
1287 1287
                                   ->load_model('Ticket', array($evtobj->get_timezone()))
1288 1288
                                   ->get_one_by_ID($tkt['TKT_ID']);
@@ -1322,7 +1322,7 @@  discard block
 block discarded – undo
1322 1322
                         $TKT->set('TKT_deleted', 1);
1323 1323
                         $TKT->save();
1324 1324
                         // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1325
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1325
+                        $saved_tickets[$TKT->ID()] = $TKT;
1326 1326
                         // 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.
1327 1327
                         $TKT = clone $TKT;
1328 1328
                         $TKT->set('TKT_ID', 0);
@@ -1367,9 +1367,9 @@  discard block
 block discarded – undo
1367 1367
             }
1368 1368
             // initially let's add the ticket to the dtt
1369 1369
             $saved_dtt->_add_relation_to($TKT, 'Ticket');
1370
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1370
+            $saved_tickets[$TKT->ID()] = $TKT;
1371 1371
             // add prices to ticket
1372
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1372
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1373 1373
         }
1374 1374
         // 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.
1375 1375
         $old_tickets = isset($old_tickets[0]) && $old_tickets[0] === '' ? array() : $old_tickets;
@@ -1537,7 +1537,7 @@  discard block
 block discarded – undo
1537 1537
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1538 1538
         // load template
1539 1539
         EEH_Template::display_template(
1540
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1540
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1541 1541
             $publish_box_extra_args
1542 1542
         );
1543 1543
     }
@@ -1572,9 +1572,9 @@  discard block
 block discarded – undo
1572 1572
         if (EE_Registry::instance()->CFG->admin->useAdvancedEditor()) {
1573 1573
             add_action(
1574 1574
                 'add_meta_boxes_espresso_events',
1575
-                function () {
1575
+                function() {
1576 1576
                     global $current_screen;
1577
-                    remove_meta_box( 'authordiv' , $current_screen , 'normal' );
1577
+                    remove_meta_box('authordiv', $current_screen, 'normal');
1578 1578
                 },
1579 1579
                 99
1580 1580
             );
@@ -1648,7 +1648,7 @@  discard block
 block discarded – undo
1648 1648
                     'default_where_conditions' => 'none',
1649 1649
                 )
1650 1650
             );
1651
-            if (! empty($related_tickets)) {
1651
+            if ( ! empty($related_tickets)) {
1652 1652
                 $template_args['total_ticket_rows'] = count($related_tickets);
1653 1653
                 $row = 0;
1654 1654
                 foreach ($related_tickets as $ticket) {
@@ -1682,7 +1682,7 @@  discard block
 block discarded – undo
1682 1682
         );
1683 1683
         $template = apply_filters(
1684 1684
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1685
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1685
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1686 1686
         );
1687 1687
         EEH_Template::display_template($template, $template_args);
1688 1688
     }
@@ -1706,7 +1706,7 @@  discard block
 block discarded – undo
1706 1706
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1707 1707
     {
1708 1708
         $template_args = array(
1709
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1709
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1710 1710
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1711 1711
                 : '',
1712 1712
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1718,10 +1718,10 @@  discard block
 block discarded – undo
1718 1718
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1719 1719
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1720 1720
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1721
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1722
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1721
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1722
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1723 1723
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1724
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1724
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1725 1725
                 : ' disabled=disabled',
1726 1726
         );
1727 1727
         $price = $ticket->ID() !== 0
@@ -1748,7 +1748,7 @@  discard block
 block discarded – undo
1748 1748
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1749 1749
                 )
1750 1750
                 : null;
1751
-            if (! empty($earliest_dtt)) {
1751
+            if ( ! empty($earliest_dtt)) {
1752 1752
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1753 1753
             } else {
1754 1754
                 $template_args['TKT_end_date'] = date(
@@ -1760,7 +1760,7 @@  discard block
 block discarded – undo
1760 1760
         $template_args = array_merge($template_args, $price_args);
1761 1761
         $template = apply_filters(
1762 1762
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1763
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1763
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1764 1764
             $ticket
1765 1765
         );
1766 1766
         return EEH_Template::display_template($template, $template_args, true);
@@ -1815,7 +1815,7 @@  discard block
 block discarded – undo
1815 1815
             $default_reg_status_values
1816 1816
         );
1817 1817
         EEH_Template::display_template(
1818
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1818
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1819 1819
             $template_args
1820 1820
         );
1821 1821
     }
@@ -1845,7 +1845,7 @@  discard block
 block discarded – undo
1845 1845
     {
1846 1846
         $EEME = $this->_event_model();
1847 1847
         $offset = ($current_page - 1) * $per_page;
1848
-        $limit = $count ? null : $offset . ',' . $per_page;
1848
+        $limit = $count ? null : $offset.','.$per_page;
1849 1849
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1850 1850
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
1851 1851
         if (isset($this->_req_data['month_range'])) {
@@ -1874,7 +1874,7 @@  discard block
 block discarded – undo
1874 1874
         // categories?
1875 1875
         $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1876 1876
             ? $this->_req_data['EVT_CAT'] : null;
1877
-        if (! empty($category)) {
1877
+        if ( ! empty($category)) {
1878 1878
             $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1879 1879
             $where['Term_Taxonomy.term_id'] = $category;
1880 1880
         }
@@ -1882,7 +1882,7 @@  discard block
 block discarded – undo
1882 1882
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1883 1883
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] !== '') {
1884 1884
             $DateTime = new DateTime(
1885
-                $year_r . '-' . $month_r . '-01 00:00:00',
1885
+                $year_r.'-'.$month_r.'-01 00:00:00',
1886 1886
                 new DateTimeZone('UTC')
1887 1887
             );
1888 1888
             $start = $DateTime->getTimestamp();
@@ -1908,9 +1908,9 @@  discard block
 block discarded – undo
1908 1908
                             ->format(implode(' ', $start_formats));
1909 1909
             $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1910 1910
         }
1911
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1911
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1912 1912
             $where['EVT_wp_user'] = get_current_user_id();
1913
-        } elseif (! isset($where['status'])
1913
+        } elseif ( ! isset($where['status'])
1914 1914
             && ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')
1915 1915
         ) {
1916 1916
             $where['OR'] = array(
@@ -1930,7 +1930,7 @@  discard block
 block discarded – undo
1930 1930
         }
1931 1931
         // search query handling
1932 1932
         if (isset($this->_req_data['s'])) {
1933
-            $search_string = '%' . $this->_req_data['s'] . '%';
1933
+            $search_string = '%'.$this->_req_data['s'].'%';
1934 1934
             $where['OR'] = array(
1935 1935
                 'EVT_name'       => array('LIKE', $search_string),
1936 1936
                 'EVT_desc'       => array('LIKE', $search_string),
@@ -2045,7 +2045,7 @@  discard block
 block discarded – undo
2045 2045
             // clean status
2046 2046
             $event_status = sanitize_key($event_status);
2047 2047
             // grab status
2048
-            if (! empty($event_status)) {
2048
+            if ( ! empty($event_status)) {
2049 2049
                 $success = $this->_change_event_status($EVT_ID, $event_status);
2050 2050
             } else {
2051 2051
                 $success = false;
@@ -2087,7 +2087,7 @@  discard block
 block discarded – undo
2087 2087
         // clean status
2088 2088
         $event_status = sanitize_key($event_status);
2089 2089
         // grab status
2090
-        if (! empty($event_status)) {
2090
+        if ( ! empty($event_status)) {
2091 2091
             $success = true;
2092 2092
             // determine the event id and set to array.
2093 2093
             $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
@@ -2139,7 +2139,7 @@  discard block
 block discarded – undo
2139 2139
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2140 2140
     {
2141 2141
         // grab event id
2142
-        if (! $EVT_ID) {
2142
+        if ( ! $EVT_ID) {
2143 2143
             $msg = esc_html__(
2144 2144
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2145 2145
                 'event_espresso'
@@ -2210,8 +2210,8 @@  discard block
 block discarded – undo
2210 2210
             // get list of events with no prices
2211 2211
             $espresso_no_ticket_prices = get_option('ee_no_ticket_prices', array());
2212 2212
             // remove this event from the list of events with no prices
2213
-            if (isset($espresso_no_ticket_prices[ $EVT_ID ])) {
2214
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2213
+            if (isset($espresso_no_ticket_prices[$EVT_ID])) {
2214
+                unset($espresso_no_ticket_prices[$EVT_ID]);
2215 2215
             }
2216 2216
             update_option('ee_no_ticket_prices', $espresso_no_ticket_prices);
2217 2217
         } else {
@@ -2258,7 +2258,7 @@  discard block
 block discarded – undo
2258 2258
                 $results = $this->_permanently_delete_event($EVT_ID);
2259 2259
                 $success = $results !== false ? $success : false;
2260 2260
                 // remove this event from the list of events with no prices
2261
-                unset($espresso_no_ticket_prices[ $EVT_ID ]);
2261
+                unset($espresso_no_ticket_prices[$EVT_ID]);
2262 2262
             } else {
2263 2263
                 $success = false;
2264 2264
                 $msg = esc_html__(
@@ -2290,7 +2290,7 @@  discard block
 block discarded – undo
2290 2290
     private function _permanently_delete_event($EVT_ID = 0)
2291 2291
     {
2292 2292
         // grab event id
2293
-        if (! $EVT_ID) {
2293
+        if ( ! $EVT_ID) {
2294 2294
             $msg = esc_html__(
2295 2295
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2296 2296
                 'event_espresso'
@@ -2298,12 +2298,12 @@  discard block
 block discarded – undo
2298 2298
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2299 2299
             return false;
2300 2300
         }
2301
-        if (! $this->_cpt_model_obj instanceof EE_Event
2301
+        if ( ! $this->_cpt_model_obj instanceof EE_Event
2302 2302
             || $this->_cpt_model_obj->ID() !== $EVT_ID
2303 2303
         ) {
2304 2304
             $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2305 2305
         }
2306
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2306
+        if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2307 2307
             return false;
2308 2308
         }
2309 2309
         // need to delete related tickets and prices first.
@@ -2325,7 +2325,7 @@  discard block
 block discarded – undo
2325 2325
         }
2326 2326
         // any attached question groups?
2327 2327
         $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2328
-        if (! empty($question_groups)) {
2328
+        if ( ! empty($question_groups)) {
2329 2329
             foreach ($question_groups as $question_group) {
2330 2330
                 $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2331 2331
             }
@@ -2558,7 +2558,7 @@  discard block
 block discarded – undo
2558 2558
                                                 . esc_html__(
2559 2559
                                                     '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.',
2560 2560
                                                     'event_espresso'
2561
-                                                ) . '</strong>';
2561
+                                                ).'</strong>';
2562 2562
         $this->display_admin_caf_preview_page('template_settings_tab');
2563 2563
     }
2564 2564
 
@@ -2578,12 +2578,12 @@  discard block
 block discarded – undo
2578 2578
         // set default category object
2579 2579
         $this->_set_empty_category_object();
2580 2580
         // only set if we've got an id
2581
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2581
+        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2582 2582
             return;
2583 2583
         }
2584 2584
         $category_id = absint($this->_req_data['EVT_CAT_ID']);
2585 2585
         $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2586
-        if (! empty($term)) {
2586
+        if ( ! empty($term)) {
2587 2587
             $this->_category->category_name = $term->name;
2588 2588
             $this->_category->category_identifier = $term->slug;
2589 2589
             $this->_category->category_desc = $term->description;
@@ -2615,7 +2615,7 @@  discard block
 block discarded – undo
2615 2615
     {
2616 2616
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2617 2617
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2618
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2618
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2619 2619
             'add_category',
2620 2620
             'add_category',
2621 2621
             array(),
@@ -2698,7 +2698,7 @@  discard block
 block discarded – undo
2698 2698
             'disable'                  => '',
2699 2699
             'disabled_message'         => false,
2700 2700
         );
2701
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2701
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2702 2702
         return EEH_Template::display_template($template, $template_args, true);
2703 2703
     }
2704 2704
 
@@ -2787,7 +2787,7 @@  discard block
 block discarded – undo
2787 2787
         $insert_ids = $update
2788 2788
             ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2789 2789
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2790
-        if (! is_array($insert_ids)) {
2790
+        if ( ! is_array($insert_ids)) {
2791 2791
             $msg = esc_html__(
2792 2792
                 'An error occurred and the category has not been saved to the database.',
2793 2793
                 'event_espresso'
@@ -2822,7 +2822,7 @@  discard block
 block discarded – undo
2822 2822
         $limit = ($current_page - 1) * $per_page;
2823 2823
         $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2824 2824
         if (isset($this->_req_data['s'])) {
2825
-            $sstr = '%' . $this->_req_data['s'] . '%';
2825
+            $sstr = '%'.$this->_req_data['s'].'%';
2826 2826
             $where['OR'] = array(
2827 2827
                 'Term.name'   => array('LIKE', $sstr),
2828 2828
                 'description' => array('LIKE', $sstr),
@@ -2831,7 +2831,7 @@  discard block
 block discarded – undo
2831 2831
         $query_params = array(
2832 2832
             $where,
2833 2833
             'order_by'   => array($orderby => $order),
2834
-            'limit'      => $limit . ',' . $per_page,
2834
+            'limit'      => $limit.','.$per_page,
2835 2835
             'force_join' => array('Term'),
2836 2836
         );
2837 2837
         $categories = $count
Please login to merge, or discard this patch.
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 2 patches
Indentation   +1403 added lines, -1403 removed lines patch added patch discarded remove patch
@@ -16,1407 +16,1407 @@
 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
-        wp_register_script(
356
-            'ee-event-editor-heartbeat',
357
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
358
-            array('ee_admin_js', 'heartbeat'),
359
-            EVENT_ESPRESSO_VERSION,
360
-            true
361
-        );
362
-        wp_enqueue_script('ee-accounting');
363
-        // styles
364
-        wp_enqueue_style('espresso-ui-theme');
365
-        wp_enqueue_script('event_editor_js');
366
-        wp_enqueue_script('ee-event-editor-heartbeat');
367
-    }
368
-
369
-
370
-    /**
371
-     * Returns template for the additional datetime.
372
-     *
373
-     * @param $template
374
-     * @param $template_args
375
-     * @return mixed
376
-     * @throws DomainException
377
-     */
378
-    public function add_additional_datetime_button($template, $template_args)
379
-    {
380
-        return EEH_Template::display_template(
381
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
382
-            $template_args,
383
-            true
384
-        );
385
-    }
386
-
387
-
388
-    /**
389
-     * Returns the template for cloning a datetime.
390
-     *
391
-     * @param $template
392
-     * @param $template_args
393
-     * @return mixed
394
-     * @throws DomainException
395
-     */
396
-    public function add_datetime_clone_button($template, $template_args)
397
-    {
398
-        return EEH_Template::display_template(
399
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
400
-            $template_args,
401
-            true
402
-        );
403
-    }
404
-
405
-
406
-    /**
407
-     * Returns the template for datetime timezones.
408
-     *
409
-     * @param $template
410
-     * @param $template_args
411
-     * @return mixed
412
-     * @throws DomainException
413
-     */
414
-    public function datetime_timezones_template($template, $template_args)
415
-    {
416
-        return EEH_Template::display_template(
417
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
418
-            $template_args,
419
-            true
420
-        );
421
-    }
422
-
423
-
424
-    /**
425
-     * Sets the views for the default list table view.
426
-     *
427
-     * @throws EE_Error
428
-     */
429
-    protected function _set_list_table_views_default()
430
-    {
431
-        parent::_set_list_table_views_default();
432
-        $new_views = array(
433
-            'today' => array(
434
-                'slug'        => 'today',
435
-                'label'       => esc_html__('Today', 'event_espresso'),
436
-                'count'       => $this->total_events_today(),
437
-                'bulk_action' => array(
438
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
439
-                ),
440
-            ),
441
-            'month' => array(
442
-                'slug'        => 'month',
443
-                'label'       => esc_html__('This Month', 'event_espresso'),
444
-                'count'       => $this->total_events_this_month(),
445
-                'bulk_action' => array(
446
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
447
-                ),
448
-            ),
449
-        );
450
-        $this->_views = array_merge($this->_views, $new_views);
451
-    }
452
-
453
-
454
-    /**
455
-     * Returns the extra action links for the default list table view.
456
-     *
457
-     * @param array    $action_links
458
-     * @param EE_Event $event
459
-     * @return array
460
-     * @throws EE_Error
461
-     * @throws InvalidArgumentException
462
-     * @throws InvalidDataTypeException
463
-     * @throws InvalidInterfaceException
464
-     * @throws ReflectionException
465
-     */
466
-    public function extra_list_table_actions(array $action_links, EE_Event $event)
467
-    {
468
-        if (EE_Registry::instance()->CAP->current_user_can(
469
-            'ee_read_registrations',
470
-            'espresso_registrations_reports',
471
-            $event->ID()
472
-        )
473
-        ) {
474
-            $reports_query_args = array(
475
-                'action' => 'reports',
476
-                'EVT_ID' => $event->ID(),
477
-            );
478
-            $reports_link = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
479
-            $action_links[] = '<a href="'
480
-                              . $reports_link
481
-                              . '" title="'
482
-                              . esc_attr__('View Report', 'event_espresso')
483
-                              . '"><div class="dashicons dashicons-chart-bar"></div></a>'
484
-                              . "\n\t";
485
-        }
486
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
487
-            EE_Registry::instance()->load_helper('MSG_Template');
488
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
489
-                'see_notifications_for',
490
-                null,
491
-                array('EVT_ID' => $event->ID())
492
-            );
493
-        }
494
-        return $action_links;
495
-    }
496
-
497
-
498
-    /**
499
-     * @param $items
500
-     * @return mixed
501
-     */
502
-    public function additional_legend_items($items)
503
-    {
504
-        if (EE_Registry::instance()->CAP->current_user_can(
505
-            'ee_read_registrations',
506
-            'espresso_registrations_reports'
507
-        )
508
-        ) {
509
-            $items['reports'] = array(
510
-                'class' => 'dashicons dashicons-chart-bar',
511
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
512
-            );
513
-        }
514
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
515
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
516
-            // $related_for_icon can sometimes be a string so 'css_class' would be an illegal offset
517
-            // (can only use numeric offsets when treating strings as arrays)
518
-            if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
519
-                $items['view_related_messages'] = array(
520
-                    'class' => $related_for_icon['css_class'],
521
-                    'desc'  => $related_for_icon['label'],
522
-                );
523
-            }
524
-        }
525
-        return $items;
526
-    }
527
-
528
-
529
-    /**
530
-     * This is the callback method for the duplicate event route
531
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
532
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
533
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
534
-     * After duplication the redirect is to the new event edit page.
535
-     *
536
-     * @return void
537
-     * @throws EE_Error If EE_Event is not available with given ID
538
-     * @throws InvalidArgumentException
539
-     * @throws InvalidDataTypeException
540
-     * @throws InvalidInterfaceException
541
-     * @throws ReflectionException
542
-     * @access protected
543
-     */
544
-    protected function _duplicate_event()
545
-    {
546
-        // first make sure the ID for the event is in the request.
547
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
548
-        if (! isset($this->_req_data['EVT_ID'])) {
549
-            EE_Error::add_error(
550
-                esc_html__(
551
-                    'In order to duplicate an event an Event ID is required.  None was given.',
552
-                    'event_espresso'
553
-                ),
554
-                __FILE__,
555
-                __FUNCTION__,
556
-                __LINE__
557
-            );
558
-            $this->_redirect_after_action(false, '', '', array(), true);
559
-            return;
560
-        }
561
-        // k we've got EVT_ID so let's use that to get the event we'll duplicate
562
-        $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
563
-        if (! $orig_event instanceof EE_Event) {
564
-            throw new EE_Error(
565
-                sprintf(
566
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
567
-                    $this->_req_data['EVT_ID']
568
-                )
569
-            );
570
-        }
571
-        // k now let's clone the $orig_event before getting relations
572
-        $new_event = clone $orig_event;
573
-        // original datetimes
574
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
575
-        // other original relations
576
-        $orig_ven = $orig_event->get_many_related('Venue');
577
-        // reset the ID and modify other details to make it clear this is a dupe
578
-        $new_event->set('EVT_ID', 0);
579
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
580
-        $new_event->set('EVT_name', $new_name);
581
-        $new_event->set(
582
-            'EVT_slug',
583
-            wp_unique_post_slug(
584
-                sanitize_title($orig_event->name()),
585
-                0,
586
-                'publish',
587
-                'espresso_events',
588
-                0
589
-            )
590
-        );
591
-        $new_event->set('status', 'draft');
592
-        // duplicate discussion settings
593
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
594
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
595
-        // save the new event
596
-        $new_event->save();
597
-        // venues
598
-        foreach ($orig_ven as $ven) {
599
-            $new_event->_add_relation_to($ven, 'Venue');
600
-        }
601
-        $new_event->save();
602
-        // now we need to get the question group relations and handle that
603
-        // first primary question groups
604
-        $orig_primary_qgs = $orig_event->get_many_related(
605
-            'Question_Group',
606
-            [['Event_Question_Group.EQG_primary' => true]]
607
-        );
608
-        if (! empty($orig_primary_qgs)) {
609
-            foreach ($orig_primary_qgs as $id => $obj) {
610
-                if ($obj instanceof EE_Question_Group) {
611
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
612
-                }
613
-            }
614
-        }
615
-        // next additional attendee question groups
616
-        $orig_additional_qgs = $orig_event->get_many_related(
617
-            'Question_Group',
618
-            [['Event_Question_Group.EQG_additional' => true]]
619
-        );
620
-        if (! empty($orig_additional_qgs)) {
621
-            foreach ($orig_additional_qgs as $id => $obj) {
622
-                if ($obj instanceof EE_Question_Group) {
623
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
624
-                }
625
-            }
626
-        }
627
-
628
-        $new_event->save();
629
-
630
-        // k now that we have the new event saved we can loop through the datetimes and start adding relations.
631
-        $cloned_tickets = array();
632
-        foreach ($orig_datetimes as $orig_dtt) {
633
-            if (! $orig_dtt instanceof EE_Datetime) {
634
-                continue;
635
-            }
636
-            $new_dtt = clone $orig_dtt;
637
-            $orig_tkts = $orig_dtt->tickets();
638
-            // save new dtt then add to event
639
-            $new_dtt->set('DTT_ID', 0);
640
-            $new_dtt->set('DTT_sold', 0);
641
-            $new_dtt->set_reserved(0);
642
-            $new_dtt->save();
643
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
644
-            $new_event->save();
645
-            // now let's get the ticket relations setup.
646
-            foreach ((array) $orig_tkts as $orig_tkt) {
647
-                // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
648
-                if (! $orig_tkt instanceof EE_Ticket) {
649
-                    continue;
650
-                }
651
-                // is this ticket archived?  If it is then let's skip
652
-                if ($orig_tkt->get('TKT_deleted')) {
653
-                    continue;
654
-                }
655
-                // does this original ticket already exist in the clone_tickets cache?
656
-                //  If so we'll just use the new ticket from it.
657
-                if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
658
-                    $new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
659
-                } else {
660
-                    $new_tkt = clone $orig_tkt;
661
-                    // get relations on the $orig_tkt that we need to setup.
662
-                    $orig_prices = $orig_tkt->prices();
663
-                    $new_tkt->set('TKT_ID', 0);
664
-                    $new_tkt->set('TKT_sold', 0);
665
-                    $new_tkt->set('TKT_reserved', 0);
666
-                    $new_tkt->save(); // make sure new ticket has ID.
667
-                    // price relations on new ticket need to be setup.
668
-                    foreach ($orig_prices as $orig_price) {
669
-                        $new_price = clone $orig_price;
670
-                        $new_price->set('PRC_ID', 0);
671
-                        $new_price->save();
672
-                        $new_tkt->_add_relation_to($new_price, 'Price');
673
-                        $new_tkt->save();
674
-                    }
675
-
676
-                    do_action(
677
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
678
-                        $orig_tkt,
679
-                        $new_tkt,
680
-                        $orig_prices,
681
-                        $orig_event,
682
-                        $orig_dtt,
683
-                        $new_dtt
684
-                    );
685
-                }
686
-                // k now we can add the new ticket as a relation to the new datetime
687
-                // and make sure its added to our cached $cloned_tickets array
688
-                // for use with later datetimes that have the same ticket.
689
-                $new_dtt->_add_relation_to($new_tkt, 'Ticket');
690
-                $new_dtt->save();
691
-                $cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
692
-            }
693
-        }
694
-        // clone taxonomy information
695
-        $taxonomies_to_clone_with = apply_filters(
696
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
697
-            array('espresso_event_categories', 'espresso_event_type', 'post_tag')
698
-        );
699
-        // get terms for original event (notice)
700
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
701
-        // loop through terms and add them to new event.
702
-        foreach ($orig_terms as $term) {
703
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
704
-        }
705
-
706
-        // duplicate other core WP_Post items for this event.
707
-        // post thumbnail (feature image).
708
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
709
-        if ($feature_image_id) {
710
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
711
-        }
712
-
713
-        // duplicate page_template setting
714
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
715
-        if ($page_template) {
716
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
717
-        }
718
-
719
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
720
-        // now let's redirect to the edit page for this duplicated event if we have a new event id.
721
-        if ($new_event->ID()) {
722
-            $redirect_args = array(
723
-                'post'   => $new_event->ID(),
724
-                'action' => 'edit',
725
-            );
726
-            EE_Error::add_success(
727
-                esc_html__(
728
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
729
-                    'event_espresso'
730
-                )
731
-            );
732
-        } else {
733
-            $redirect_args = array(
734
-                'action' => 'default',
735
-            );
736
-            EE_Error::add_error(
737
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
738
-                __FILE__,
739
-                __FUNCTION__,
740
-                __LINE__
741
-            );
742
-        }
743
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
744
-    }
745
-
746
-
747
-    /**
748
-     * Generates output for the import page.
749
-     *
750
-     * @throws DomainException
751
-     * @throws EE_Error
752
-     * @throws InvalidArgumentException
753
-     * @throws InvalidDataTypeException
754
-     * @throws InvalidInterfaceException
755
-     */
756
-    protected function _import_page()
757
-    {
758
-        $title = esc_html__('Import', 'event_espresso');
759
-        $intro = esc_html__(
760
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
761
-            'event_espresso'
762
-        );
763
-        $form_url = EVENTS_ADMIN_URL;
764
-        $action = 'import_events';
765
-        $type = 'csv';
766
-        $this->_template_args['form'] = EE_Import::instance()->upload_form(
767
-            $title,
768
-            $intro,
769
-            $form_url,
770
-            $action,
771
-            $type
772
-        );
773
-        $this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
774
-            array('action' => 'sample_export_file'),
775
-            $this->_admin_base_url
776
-        );
777
-        $content = EEH_Template::display_template(
778
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
779
-            $this->_template_args,
780
-            true
781
-        );
782
-        $this->_template_args['admin_page_content'] = $content;
783
-        $this->display_admin_page_with_sidebar();
784
-    }
785
-
786
-
787
-    /**
788
-     * _import_events
789
-     * This handles displaying the screen and running imports for importing events.
790
-     *
791
-     * @return void
792
-     * @throws EE_Error
793
-     * @throws InvalidArgumentException
794
-     * @throws InvalidDataTypeException
795
-     * @throws InvalidInterfaceException
796
-     */
797
-    protected function _import_events()
798
-    {
799
-        require_once(EE_CLASSES . 'EE_Import.class.php');
800
-        $success = EE_Import::instance()->import();
801
-        $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
802
-    }
803
-
804
-
805
-    /**
806
-     * _events_export
807
-     * Will export all (or just the given event) to a Excel compatible file.
808
-     *
809
-     * @access protected
810
-     * @return void
811
-     */
812
-    protected function _events_export()
813
-    {
814
-        if (isset($this->_req_data['EVT_ID'])) {
815
-            $event_ids = $this->_req_data['EVT_ID'];
816
-        } elseif (isset($this->_req_data['EVT_IDs'])) {
817
-            $event_ids = $this->_req_data['EVT_IDs'];
818
-        } else {
819
-            $event_ids = null;
820
-        }
821
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
822
-        $new_request_args = array(
823
-            'export' => 'report',
824
-            'action' => 'all_event_data',
825
-            'EVT_ID' => $event_ids,
826
-        );
827
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
828
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
829
-            require_once(EE_CLASSES . 'EE_Export.class.php');
830
-            $EE_Export = EE_Export::instance($this->_req_data);
831
-            if ($EE_Export instanceof EE_Export) {
832
-                $EE_Export->export();
833
-            }
834
-        }
835
-    }
836
-
837
-
838
-    /**
839
-     * handle category exports()
840
-     *
841
-     * @return void
842
-     */
843
-    protected function _categories_export()
844
-    {
845
-        // todo: I don't like doing this but it'll do until we modify EE_Export Class.
846
-        $new_request_args = array(
847
-            'export'       => 'report',
848
-            'action'       => 'categories',
849
-            'category_ids' => $this->_req_data['EVT_CAT_ID'],
850
-        );
851
-        $this->_req_data = array_merge($this->_req_data, $new_request_args);
852
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
853
-            require_once(EE_CLASSES . 'EE_Export.class.php');
854
-            $EE_Export = EE_Export::instance($this->_req_data);
855
-            if ($EE_Export instanceof EE_Export) {
856
-                $EE_Export->export();
857
-            }
858
-        }
859
-    }
860
-
861
-
862
-    /**
863
-     * Creates a sample CSV file for importing
864
-     */
865
-    protected function _sample_export_file()
866
-    {
867
-        $EE_Export = EE_Export::instance();
868
-        if ($EE_Export instanceof EE_Export) {
869
-            $EE_Export->export();
870
-        }
871
-    }
872
-
873
-
874
-    /*************        Template Settings        *************/
875
-    /**
876
-     * Generates template settings page output
877
-     *
878
-     * @throws DomainException
879
-     * @throws EE_Error
880
-     * @throws InvalidArgumentException
881
-     * @throws InvalidDataTypeException
882
-     * @throws InvalidInterfaceException
883
-     */
884
-    protected function _template_settings()
885
-    {
886
-        $this->_template_args['values'] = $this->_yes_no_values;
887
-        /**
888
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
889
-         * from General_Settings_Admin_Page to here.
890
-         */
891
-        $this->_template_args = apply_filters(
892
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
893
-            $this->_template_args
894
-        );
895
-        $this->_set_add_edit_form_tags('update_template_settings');
896
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
897
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
898
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
899
-            $this->_template_args,
900
-            true
901
-        );
902
-        $this->display_admin_page_with_sidebar();
903
-    }
904
-
905
-
906
-    /**
907
-     * Handler for updating template settings.
908
-     *
909
-     * @throws EE_Error
910
-     * @throws InvalidArgumentException
911
-     * @throws InvalidDataTypeException
912
-     * @throws InvalidInterfaceException
913
-     */
914
-    protected function _update_template_settings()
915
-    {
916
-        /**
917
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
918
-         * from General_Settings_Admin_Page to here.
919
-         */
920
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
921
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
922
-            EE_Registry::instance()->CFG->template_settings,
923
-            $this->_req_data
924
-        );
925
-        // update custom post type slugs and detect if we need to flush rewrite rules
926
-        $old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
927
-        EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
928
-            ? EE_Registry::instance()->CFG->core->event_cpt_slug
929
-            : EEH_URL::slugify($this->_req_data['event_cpt_slug'], 'events');
930
-        $what = 'Template Settings';
931
-        $success = $this->_update_espresso_configuration(
932
-            $what,
933
-            EE_Registry::instance()->CFG->template_settings,
934
-            __FILE__,
935
-            __FUNCTION__,
936
-            __LINE__
937
-        );
938
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug !== $old_slug) {
939
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
940
-            $rewrite_rules = LoaderFactory::getLoader()->getShared(
941
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
942
-            );
943
-            $rewrite_rules->flush();
944
-        }
945
-        $this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
946
-    }
947
-
948
-
949
-    /**
950
-     * _premium_event_editor_meta_boxes
951
-     * add all metaboxes related to the event_editor
952
-     *
953
-     * @access protected
954
-     * @return void
955
-     * @throws EE_Error
956
-     * @throws InvalidArgumentException
957
-     * @throws InvalidDataTypeException
958
-     * @throws InvalidInterfaceException
959
-     * @throws ReflectionException
960
-     */
961
-    protected function _premium_event_editor_meta_boxes()
962
-    {
963
-        $this->verify_cpt_object();
964
-        add_meta_box(
965
-            'espresso_event_editor_event_options',
966
-            esc_html__('Event Registration Options', 'event_espresso'),
967
-            array($this, 'registration_options_meta_box'),
968
-            $this->page_slug,
969
-            'side',
970
-            'core'
971
-        );
972
-    }
973
-
974
-
975
-    /**
976
-     * override caf metabox
977
-     *
978
-     * @return void
979
-     * @throws DomainException
980
-     * @throws EE_Error
981
-     */
982
-    public function registration_options_meta_box()
983
-    {
984
-        $yes_no_values = array(
985
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
986
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
987
-        );
988
-        $default_reg_status_values = EEM_Registration::reg_status_array(
989
-            array(
990
-                EEM_Registration::status_id_cancelled,
991
-                EEM_Registration::status_id_declined,
992
-                EEM_Registration::status_id_incomplete,
993
-                EEM_Registration::status_id_wait_list,
994
-            ),
995
-            true
996
-        );
997
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
998
-        $template_args['_event'] = $this->_cpt_model_obj;
999
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1000
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1001
-            'default_reg_status',
1002
-            $default_reg_status_values,
1003
-            $this->_cpt_model_obj->default_registration_status()
1004
-        );
1005
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1006
-            'display_desc',
1007
-            $yes_no_values,
1008
-            $this->_cpt_model_obj->display_description()
1009
-        );
1010
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1011
-            'display_ticket_selector',
1012
-            $yes_no_values,
1013
-            $this->_cpt_model_obj->display_ticket_selector(),
1014
-            '',
1015
-            '',
1016
-            false
1017
-        );
1018
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
1019
-            'EVT_default_registration_status',
1020
-            $default_reg_status_values,
1021
-            $this->_cpt_model_obj->default_registration_status()
1022
-        );
1023
-        $template_args['additional_registration_options'] = apply_filters(
1024
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1025
-            '',
1026
-            $template_args,
1027
-            $yes_no_values,
1028
-            $default_reg_status_values
1029
-        );
1030
-        EEH_Template::display_template(
1031
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
1032
-            $template_args
1033
-        );
1034
-    }
1035
-
1036
-
1037
-
1038
-    /**
1039
-     * wp_list_table_mods for caf
1040
-     * ============================
1041
-     */
1042
-    /**
1043
-     * hook into list table filters and provide filters for caffeinated list table
1044
-     *
1045
-     * @param array $old_filters    any existing filters present
1046
-     * @param array $list_table_obj the list table object
1047
-     * @return array                  new filters
1048
-     * @throws EE_Error
1049
-     * @throws InvalidArgumentException
1050
-     * @throws InvalidDataTypeException
1051
-     * @throws InvalidInterfaceException
1052
-     * @throws ReflectionException
1053
-     */
1054
-    public function list_table_filters($old_filters, $list_table_obj)
1055
-    {
1056
-        $filters = array();
1057
-        // first month/year filters
1058
-        $filters[] = $this->espresso_event_months_dropdown();
1059
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1060
-        // active status dropdown
1061
-        if ($status !== 'draft') {
1062
-            $filters[] = $this->active_status_dropdown(
1063
-                isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
1064
-            );
1065
-            $filters[] = $this->venuesDropdown(
1066
-                isset($this->_req_data['venue']) ? $this->_req_data['venue'] : ''
1067
-            );
1068
-        }
1069
-        // category filter
1070
-        $filters[] = $this->category_dropdown();
1071
-        return array_merge($old_filters, $filters);
1072
-    }
1073
-
1074
-
1075
-    /**
1076
-     * espresso_event_months_dropdown
1077
-     *
1078
-     * @access public
1079
-     * @return string                dropdown listing month/year selections for events.
1080
-     */
1081
-    public function espresso_event_months_dropdown()
1082
-    {
1083
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
1084
-        // Note we need to include any other filters that are set!
1085
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1086
-        // categories?
1087
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1088
-            ? $this->_req_data['EVT_CAT']
1089
-            : null;
1090
-        // active status?
1091
-        $active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
1092
-        $cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1093
-        return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1094
-    }
1095
-
1096
-
1097
-    /**
1098
-     * returns a list of "active" statuses on the event
1099
-     *
1100
-     * @param  string $current_value whatever the current active status is
1101
-     * @return string
1102
-     */
1103
-    public function active_status_dropdown($current_value = '')
1104
-    {
1105
-        $select_name = 'active_status';
1106
-        $values = array(
1107
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1108
-            'active'   => esc_html__('Active', 'event_espresso'),
1109
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1110
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1111
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1112
-        );
1113
-
1114
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1115
-    }
1116
-
1117
-
1118
-    /**
1119
-     * returns a list of "venues"
1120
-     *
1121
-     * @param string $current_value whatever the current active status is
1122
-     * @return string
1123
-     * @throws EE_Error
1124
-     * @throws InvalidArgumentException
1125
-     * @throws InvalidDataTypeException
1126
-     * @throws InvalidInterfaceException
1127
-     * @throws ReflectionException
1128
-     */
1129
-    protected function venuesDropdown($current_value = '')
1130
-    {
1131
-        $select_name = 'venue';
1132
-        $values = array(
1133
-            '' => esc_html__('All Venues', 'event_espresso'),
1134
-        );
1135
-        // populate the list of venues.
1136
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1137
-        $venues = $venue_model->get_all(array('order_by' => array('VNU_name' => 'ASC')));
1138
-
1139
-        foreach ($venues as $venue) {
1140
-            $values[ $venue->ID() ] = $venue->name();
1141
-        }
1142
-
1143
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1144
-    }
1145
-
1146
-
1147
-    /**
1148
-     * output a dropdown of the categories for the category filter on the event admin list table
1149
-     *
1150
-     * @access  public
1151
-     * @return string html
1152
-     */
1153
-    public function category_dropdown()
1154
-    {
1155
-        $cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1156
-        return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1157
-    }
1158
-
1159
-
1160
-    /**
1161
-     * get total number of events today
1162
-     *
1163
-     * @access public
1164
-     * @return int
1165
-     * @throws EE_Error
1166
-     * @throws InvalidArgumentException
1167
-     * @throws InvalidDataTypeException
1168
-     * @throws InvalidInterfaceException
1169
-     */
1170
-    public function total_events_today()
1171
-    {
1172
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1173
-            'DTT_EVT_start',
1174
-            date('Y-m-d') . ' 00:00:00',
1175
-            'Y-m-d H:i:s',
1176
-            'UTC'
1177
-        );
1178
-        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1179
-            'DTT_EVT_start',
1180
-            date('Y-m-d') . ' 23:59:59',
1181
-            'Y-m-d H:i:s',
1182
-            'UTC'
1183
-        );
1184
-        $where = array(
1185
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1186
-        );
1187
-        return EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1188
-    }
1189
-
1190
-
1191
-    /**
1192
-     * get total number of events this month
1193
-     *
1194
-     * @access public
1195
-     * @return int
1196
-     * @throws EE_Error
1197
-     * @throws InvalidArgumentException
1198
-     * @throws InvalidDataTypeException
1199
-     * @throws InvalidInterfaceException
1200
-     */
1201
-    public function total_events_this_month()
1202
-    {
1203
-        // Dates
1204
-        $this_year_r = date('Y');
1205
-        $this_month_r = date('m');
1206
-        $days_this_month = date('t');
1207
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1208
-            'DTT_EVT_start',
1209
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1210
-            'Y-m-d H:i:s',
1211
-            'UTC'
1212
-        );
1213
-        $end = EEM_Datetime::instance()->convert_datetime_for_query(
1214
-            'DTT_EVT_start',
1215
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1216
-            'Y-m-d H:i:s',
1217
-            'UTC'
1218
-        );
1219
-        $where = array(
1220
-            'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1221
-        );
1222
-        return EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1223
-    }
1224
-
1225
-
1226
-    /** DEFAULT TICKETS STUFF **/
1227
-
1228
-    /**
1229
-     * Output default tickets list table view.
1230
-     *
1231
-     * @throws DomainException
1232
-     * @throws EE_Error
1233
-     * @throws InvalidArgumentException
1234
-     * @throws InvalidDataTypeException
1235
-     * @throws InvalidInterfaceException
1236
-     */
1237
-    public function _tickets_overview_list_table()
1238
-    {
1239
-        $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1240
-        $this->display_admin_list_table_page_with_no_sidebar();
1241
-    }
1242
-
1243
-
1244
-    /**
1245
-     * @param int  $per_page
1246
-     * @param bool $count
1247
-     * @param bool $trashed
1248
-     * @return EE_Soft_Delete_Base_Class[]|int
1249
-     * @throws EE_Error
1250
-     * @throws InvalidArgumentException
1251
-     * @throws InvalidDataTypeException
1252
-     * @throws InvalidInterfaceException
1253
-     */
1254
-    public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1255
-    {
1256
-        $orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1257
-        $order = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1258
-        switch ($orderby) {
1259
-            case 'TKT_name':
1260
-                $orderby = array('TKT_name' => $order);
1261
-                break;
1262
-            case 'TKT_price':
1263
-                $orderby = array('TKT_price' => $order);
1264
-                break;
1265
-            case 'TKT_uses':
1266
-                $orderby = array('TKT_uses' => $order);
1267
-                break;
1268
-            case 'TKT_min':
1269
-                $orderby = array('TKT_min' => $order);
1270
-                break;
1271
-            case 'TKT_max':
1272
-                $orderby = array('TKT_max' => $order);
1273
-                break;
1274
-            case 'TKT_qty':
1275
-                $orderby = array('TKT_qty' => $order);
1276
-                break;
1277
-        }
1278
-        $current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1279
-            ? $this->_req_data['paged']
1280
-            : 1;
1281
-        $per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1282
-            ? $this->_req_data['perpage']
1283
-            : $per_page;
1284
-        $_where = array(
1285
-            'TKT_is_default' => 1,
1286
-            'TKT_deleted'    => $trashed,
1287
-        );
1288
-        $offset = ($current_page - 1) * $per_page;
1289
-        $limit = array($offset, $per_page);
1290
-        if (isset($this->_req_data['s'])) {
1291
-            $sstr = '%' . $this->_req_data['s'] . '%';
1292
-            $_where['OR'] = array(
1293
-                'TKT_name'        => array('LIKE', $sstr),
1294
-                'TKT_description' => array('LIKE', $sstr),
1295
-            );
1296
-        }
1297
-        $query_params = array(
1298
-            $_where,
1299
-            'order_by' => $orderby,
1300
-            'limit'    => $limit,
1301
-            'group_by' => 'TKT_ID',
1302
-        );
1303
-        if ($count) {
1304
-            return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1305
-        }
1306
-        return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1307
-    }
1308
-
1309
-
1310
-    /**
1311
-     * @param bool $trash
1312
-     * @throws EE_Error
1313
-     * @throws InvalidArgumentException
1314
-     * @throws InvalidDataTypeException
1315
-     * @throws InvalidInterfaceException
1316
-     */
1317
-    protected function _trash_or_restore_ticket($trash = false)
1318
-    {
1319
-        $success = 1;
1320
-        $TKT = EEM_Ticket::instance();
1321
-        // checkboxes?
1322
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1323
-            // if array has more than one element then success message should be plural
1324
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1325
-            // cycle thru the boxes
1326
-            foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1327
-                if ($trash) {
1328
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1329
-                        $success = 0;
1330
-                    }
1331
-                } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1332
-                    $success = 0;
1333
-                }
1334
-            }
1335
-        } else {
1336
-            // grab single id and trash
1337
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1338
-            if ($trash) {
1339
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1340
-                    $success = 0;
1341
-                }
1342
-            } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1343
-                $success = 0;
1344
-            }
1345
-        }
1346
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1347
-        $query_args = array(
1348
-            'action' => 'ticket_list_table',
1349
-            'status' => $trash ? '' : 'trashed',
1350
-        );
1351
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1352
-    }
1353
-
1354
-
1355
-    /**
1356
-     * Handles trashing default ticket.
1357
-     *
1358
-     * @throws EE_Error
1359
-     * @throws InvalidArgumentException
1360
-     * @throws InvalidDataTypeException
1361
-     * @throws InvalidInterfaceException
1362
-     * @throws ReflectionException
1363
-     */
1364
-    protected function _delete_ticket()
1365
-    {
1366
-        $success = 1;
1367
-        // checkboxes?
1368
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1369
-            // if array has more than one element then success message should be plural
1370
-            $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1371
-            // cycle thru the boxes
1372
-            foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1373
-                // delete
1374
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1375
-                    $success = 0;
1376
-                }
1377
-            }
1378
-        } else {
1379
-            // grab single id and trash
1380
-            $TKT_ID = absint($this->_req_data['TKT_ID']);
1381
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1382
-                $success = 0;
1383
-            }
1384
-        }
1385
-        $action_desc = 'deleted';
1386
-        // fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1387
-        $ticket_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
1388
-            [['TKT_is_default' => 1]],
1389
-            'TKT_ID',
1390
-            true
1391
-        );
1392
-        $query_args = $ticket_count
1393
-            ? []
1394
-            : [
1395
-                'action' => 'ticket_list_table',
1396
-                'status' => 'trashed'
1397
-            ];
1398
-        $this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1399
-    }
1400
-
1401
-
1402
-    /**
1403
-     * @param int $TKT_ID
1404
-     * @return bool|int
1405
-     * @throws EE_Error
1406
-     * @throws InvalidArgumentException
1407
-     * @throws InvalidDataTypeException
1408
-     * @throws InvalidInterfaceException
1409
-     * @throws ReflectionException
1410
-     */
1411
-    protected function _delete_the_ticket($TKT_ID)
1412
-    {
1413
-        $ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1414
-        if (! $ticket instanceof EE_Ticket) {
1415
-            return false;
1416
-        }
1417
-        $ticket->_remove_relations('Datetime');
1418
-        // delete all related prices first
1419
-        $ticket->delete_related_permanently('Price');
1420
-        return $ticket->delete_permanently();
1421
-    }
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
+		wp_register_script(
356
+			'ee-event-editor-heartbeat',
357
+			EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
358
+			array('ee_admin_js', 'heartbeat'),
359
+			EVENT_ESPRESSO_VERSION,
360
+			true
361
+		);
362
+		wp_enqueue_script('ee-accounting');
363
+		// styles
364
+		wp_enqueue_style('espresso-ui-theme');
365
+		wp_enqueue_script('event_editor_js');
366
+		wp_enqueue_script('ee-event-editor-heartbeat');
367
+	}
368
+
369
+
370
+	/**
371
+	 * Returns template for the additional datetime.
372
+	 *
373
+	 * @param $template
374
+	 * @param $template_args
375
+	 * @return mixed
376
+	 * @throws DomainException
377
+	 */
378
+	public function add_additional_datetime_button($template, $template_args)
379
+	{
380
+		return EEH_Template::display_template(
381
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
382
+			$template_args,
383
+			true
384
+		);
385
+	}
386
+
387
+
388
+	/**
389
+	 * Returns the template for cloning a datetime.
390
+	 *
391
+	 * @param $template
392
+	 * @param $template_args
393
+	 * @return mixed
394
+	 * @throws DomainException
395
+	 */
396
+	public function add_datetime_clone_button($template, $template_args)
397
+	{
398
+		return EEH_Template::display_template(
399
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
400
+			$template_args,
401
+			true
402
+		);
403
+	}
404
+
405
+
406
+	/**
407
+	 * Returns the template for datetime timezones.
408
+	 *
409
+	 * @param $template
410
+	 * @param $template_args
411
+	 * @return mixed
412
+	 * @throws DomainException
413
+	 */
414
+	public function datetime_timezones_template($template, $template_args)
415
+	{
416
+		return EEH_Template::display_template(
417
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
418
+			$template_args,
419
+			true
420
+		);
421
+	}
422
+
423
+
424
+	/**
425
+	 * Sets the views for the default list table view.
426
+	 *
427
+	 * @throws EE_Error
428
+	 */
429
+	protected function _set_list_table_views_default()
430
+	{
431
+		parent::_set_list_table_views_default();
432
+		$new_views = array(
433
+			'today' => array(
434
+				'slug'        => 'today',
435
+				'label'       => esc_html__('Today', 'event_espresso'),
436
+				'count'       => $this->total_events_today(),
437
+				'bulk_action' => array(
438
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
439
+				),
440
+			),
441
+			'month' => array(
442
+				'slug'        => 'month',
443
+				'label'       => esc_html__('This Month', 'event_espresso'),
444
+				'count'       => $this->total_events_this_month(),
445
+				'bulk_action' => array(
446
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
447
+				),
448
+			),
449
+		);
450
+		$this->_views = array_merge($this->_views, $new_views);
451
+	}
452
+
453
+
454
+	/**
455
+	 * Returns the extra action links for the default list table view.
456
+	 *
457
+	 * @param array    $action_links
458
+	 * @param EE_Event $event
459
+	 * @return array
460
+	 * @throws EE_Error
461
+	 * @throws InvalidArgumentException
462
+	 * @throws InvalidDataTypeException
463
+	 * @throws InvalidInterfaceException
464
+	 * @throws ReflectionException
465
+	 */
466
+	public function extra_list_table_actions(array $action_links, EE_Event $event)
467
+	{
468
+		if (EE_Registry::instance()->CAP->current_user_can(
469
+			'ee_read_registrations',
470
+			'espresso_registrations_reports',
471
+			$event->ID()
472
+		)
473
+		) {
474
+			$reports_query_args = array(
475
+				'action' => 'reports',
476
+				'EVT_ID' => $event->ID(),
477
+			);
478
+			$reports_link = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
479
+			$action_links[] = '<a href="'
480
+							  . $reports_link
481
+							  . '" title="'
482
+							  . esc_attr__('View Report', 'event_espresso')
483
+							  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
484
+							  . "\n\t";
485
+		}
486
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
487
+			EE_Registry::instance()->load_helper('MSG_Template');
488
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
489
+				'see_notifications_for',
490
+				null,
491
+				array('EVT_ID' => $event->ID())
492
+			);
493
+		}
494
+		return $action_links;
495
+	}
496
+
497
+
498
+	/**
499
+	 * @param $items
500
+	 * @return mixed
501
+	 */
502
+	public function additional_legend_items($items)
503
+	{
504
+		if (EE_Registry::instance()->CAP->current_user_can(
505
+			'ee_read_registrations',
506
+			'espresso_registrations_reports'
507
+		)
508
+		) {
509
+			$items['reports'] = array(
510
+				'class' => 'dashicons dashicons-chart-bar',
511
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
512
+			);
513
+		}
514
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
515
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
516
+			// $related_for_icon can sometimes be a string so 'css_class' would be an illegal offset
517
+			// (can only use numeric offsets when treating strings as arrays)
518
+			if (is_array($related_for_icon) && isset($related_for_icon['css_class'], $related_for_icon['label'])) {
519
+				$items['view_related_messages'] = array(
520
+					'class' => $related_for_icon['css_class'],
521
+					'desc'  => $related_for_icon['label'],
522
+				);
523
+			}
524
+		}
525
+		return $items;
526
+	}
527
+
528
+
529
+	/**
530
+	 * This is the callback method for the duplicate event route
531
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
532
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
533
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
534
+	 * After duplication the redirect is to the new event edit page.
535
+	 *
536
+	 * @return void
537
+	 * @throws EE_Error If EE_Event is not available with given ID
538
+	 * @throws InvalidArgumentException
539
+	 * @throws InvalidDataTypeException
540
+	 * @throws InvalidInterfaceException
541
+	 * @throws ReflectionException
542
+	 * @access protected
543
+	 */
544
+	protected function _duplicate_event()
545
+	{
546
+		// first make sure the ID for the event is in the request.
547
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
548
+		if (! isset($this->_req_data['EVT_ID'])) {
549
+			EE_Error::add_error(
550
+				esc_html__(
551
+					'In order to duplicate an event an Event ID is required.  None was given.',
552
+					'event_espresso'
553
+				),
554
+				__FILE__,
555
+				__FUNCTION__,
556
+				__LINE__
557
+			);
558
+			$this->_redirect_after_action(false, '', '', array(), true);
559
+			return;
560
+		}
561
+		// k we've got EVT_ID so let's use that to get the event we'll duplicate
562
+		$orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
563
+		if (! $orig_event instanceof EE_Event) {
564
+			throw new EE_Error(
565
+				sprintf(
566
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
567
+					$this->_req_data['EVT_ID']
568
+				)
569
+			);
570
+		}
571
+		// k now let's clone the $orig_event before getting relations
572
+		$new_event = clone $orig_event;
573
+		// original datetimes
574
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
575
+		// other original relations
576
+		$orig_ven = $orig_event->get_many_related('Venue');
577
+		// reset the ID and modify other details to make it clear this is a dupe
578
+		$new_event->set('EVT_ID', 0);
579
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
580
+		$new_event->set('EVT_name', $new_name);
581
+		$new_event->set(
582
+			'EVT_slug',
583
+			wp_unique_post_slug(
584
+				sanitize_title($orig_event->name()),
585
+				0,
586
+				'publish',
587
+				'espresso_events',
588
+				0
589
+			)
590
+		);
591
+		$new_event->set('status', 'draft');
592
+		// duplicate discussion settings
593
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
594
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
595
+		// save the new event
596
+		$new_event->save();
597
+		// venues
598
+		foreach ($orig_ven as $ven) {
599
+			$new_event->_add_relation_to($ven, 'Venue');
600
+		}
601
+		$new_event->save();
602
+		// now we need to get the question group relations and handle that
603
+		// first primary question groups
604
+		$orig_primary_qgs = $orig_event->get_many_related(
605
+			'Question_Group',
606
+			[['Event_Question_Group.EQG_primary' => true]]
607
+		);
608
+		if (! empty($orig_primary_qgs)) {
609
+			foreach ($orig_primary_qgs as $id => $obj) {
610
+				if ($obj instanceof EE_Question_Group) {
611
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
612
+				}
613
+			}
614
+		}
615
+		// next additional attendee question groups
616
+		$orig_additional_qgs = $orig_event->get_many_related(
617
+			'Question_Group',
618
+			[['Event_Question_Group.EQG_additional' => true]]
619
+		);
620
+		if (! empty($orig_additional_qgs)) {
621
+			foreach ($orig_additional_qgs as $id => $obj) {
622
+				if ($obj instanceof EE_Question_Group) {
623
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
624
+				}
625
+			}
626
+		}
627
+
628
+		$new_event->save();
629
+
630
+		// k now that we have the new event saved we can loop through the datetimes and start adding relations.
631
+		$cloned_tickets = array();
632
+		foreach ($orig_datetimes as $orig_dtt) {
633
+			if (! $orig_dtt instanceof EE_Datetime) {
634
+				continue;
635
+			}
636
+			$new_dtt = clone $orig_dtt;
637
+			$orig_tkts = $orig_dtt->tickets();
638
+			// save new dtt then add to event
639
+			$new_dtt->set('DTT_ID', 0);
640
+			$new_dtt->set('DTT_sold', 0);
641
+			$new_dtt->set_reserved(0);
642
+			$new_dtt->save();
643
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
644
+			$new_event->save();
645
+			// now let's get the ticket relations setup.
646
+			foreach ((array) $orig_tkts as $orig_tkt) {
647
+				// it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
648
+				if (! $orig_tkt instanceof EE_Ticket) {
649
+					continue;
650
+				}
651
+				// is this ticket archived?  If it is then let's skip
652
+				if ($orig_tkt->get('TKT_deleted')) {
653
+					continue;
654
+				}
655
+				// does this original ticket already exist in the clone_tickets cache?
656
+				//  If so we'll just use the new ticket from it.
657
+				if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
658
+					$new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
659
+				} else {
660
+					$new_tkt = clone $orig_tkt;
661
+					// get relations on the $orig_tkt that we need to setup.
662
+					$orig_prices = $orig_tkt->prices();
663
+					$new_tkt->set('TKT_ID', 0);
664
+					$new_tkt->set('TKT_sold', 0);
665
+					$new_tkt->set('TKT_reserved', 0);
666
+					$new_tkt->save(); // make sure new ticket has ID.
667
+					// price relations on new ticket need to be setup.
668
+					foreach ($orig_prices as $orig_price) {
669
+						$new_price = clone $orig_price;
670
+						$new_price->set('PRC_ID', 0);
671
+						$new_price->save();
672
+						$new_tkt->_add_relation_to($new_price, 'Price');
673
+						$new_tkt->save();
674
+					}
675
+
676
+					do_action(
677
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
678
+						$orig_tkt,
679
+						$new_tkt,
680
+						$orig_prices,
681
+						$orig_event,
682
+						$orig_dtt,
683
+						$new_dtt
684
+					);
685
+				}
686
+				// k now we can add the new ticket as a relation to the new datetime
687
+				// and make sure its added to our cached $cloned_tickets array
688
+				// for use with later datetimes that have the same ticket.
689
+				$new_dtt->_add_relation_to($new_tkt, 'Ticket');
690
+				$new_dtt->save();
691
+				$cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
692
+			}
693
+		}
694
+		// clone taxonomy information
695
+		$taxonomies_to_clone_with = apply_filters(
696
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
697
+			array('espresso_event_categories', 'espresso_event_type', 'post_tag')
698
+		);
699
+		// get terms for original event (notice)
700
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
701
+		// loop through terms and add them to new event.
702
+		foreach ($orig_terms as $term) {
703
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
704
+		}
705
+
706
+		// duplicate other core WP_Post items for this event.
707
+		// post thumbnail (feature image).
708
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
709
+		if ($feature_image_id) {
710
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
711
+		}
712
+
713
+		// duplicate page_template setting
714
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
715
+		if ($page_template) {
716
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
717
+		}
718
+
719
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
720
+		// now let's redirect to the edit page for this duplicated event if we have a new event id.
721
+		if ($new_event->ID()) {
722
+			$redirect_args = array(
723
+				'post'   => $new_event->ID(),
724
+				'action' => 'edit',
725
+			);
726
+			EE_Error::add_success(
727
+				esc_html__(
728
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
729
+					'event_espresso'
730
+				)
731
+			);
732
+		} else {
733
+			$redirect_args = array(
734
+				'action' => 'default',
735
+			);
736
+			EE_Error::add_error(
737
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
738
+				__FILE__,
739
+				__FUNCTION__,
740
+				__LINE__
741
+			);
742
+		}
743
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
744
+	}
745
+
746
+
747
+	/**
748
+	 * Generates output for the import page.
749
+	 *
750
+	 * @throws DomainException
751
+	 * @throws EE_Error
752
+	 * @throws InvalidArgumentException
753
+	 * @throws InvalidDataTypeException
754
+	 * @throws InvalidInterfaceException
755
+	 */
756
+	protected function _import_page()
757
+	{
758
+		$title = esc_html__('Import', 'event_espresso');
759
+		$intro = esc_html__(
760
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
761
+			'event_espresso'
762
+		);
763
+		$form_url = EVENTS_ADMIN_URL;
764
+		$action = 'import_events';
765
+		$type = 'csv';
766
+		$this->_template_args['form'] = EE_Import::instance()->upload_form(
767
+			$title,
768
+			$intro,
769
+			$form_url,
770
+			$action,
771
+			$type
772
+		);
773
+		$this->_template_args['sample_file_link'] = EE_Admin_Page::add_query_args_and_nonce(
774
+			array('action' => 'sample_export_file'),
775
+			$this->_admin_base_url
776
+		);
777
+		$content = EEH_Template::display_template(
778
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
779
+			$this->_template_args,
780
+			true
781
+		);
782
+		$this->_template_args['admin_page_content'] = $content;
783
+		$this->display_admin_page_with_sidebar();
784
+	}
785
+
786
+
787
+	/**
788
+	 * _import_events
789
+	 * This handles displaying the screen and running imports for importing events.
790
+	 *
791
+	 * @return void
792
+	 * @throws EE_Error
793
+	 * @throws InvalidArgumentException
794
+	 * @throws InvalidDataTypeException
795
+	 * @throws InvalidInterfaceException
796
+	 */
797
+	protected function _import_events()
798
+	{
799
+		require_once(EE_CLASSES . 'EE_Import.class.php');
800
+		$success = EE_Import::instance()->import();
801
+		$this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
802
+	}
803
+
804
+
805
+	/**
806
+	 * _events_export
807
+	 * Will export all (or just the given event) to a Excel compatible file.
808
+	 *
809
+	 * @access protected
810
+	 * @return void
811
+	 */
812
+	protected function _events_export()
813
+	{
814
+		if (isset($this->_req_data['EVT_ID'])) {
815
+			$event_ids = $this->_req_data['EVT_ID'];
816
+		} elseif (isset($this->_req_data['EVT_IDs'])) {
817
+			$event_ids = $this->_req_data['EVT_IDs'];
818
+		} else {
819
+			$event_ids = null;
820
+		}
821
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
822
+		$new_request_args = array(
823
+			'export' => 'report',
824
+			'action' => 'all_event_data',
825
+			'EVT_ID' => $event_ids,
826
+		);
827
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
828
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
829
+			require_once(EE_CLASSES . 'EE_Export.class.php');
830
+			$EE_Export = EE_Export::instance($this->_req_data);
831
+			if ($EE_Export instanceof EE_Export) {
832
+				$EE_Export->export();
833
+			}
834
+		}
835
+	}
836
+
837
+
838
+	/**
839
+	 * handle category exports()
840
+	 *
841
+	 * @return void
842
+	 */
843
+	protected function _categories_export()
844
+	{
845
+		// todo: I don't like doing this but it'll do until we modify EE_Export Class.
846
+		$new_request_args = array(
847
+			'export'       => 'report',
848
+			'action'       => 'categories',
849
+			'category_ids' => $this->_req_data['EVT_CAT_ID'],
850
+		);
851
+		$this->_req_data = array_merge($this->_req_data, $new_request_args);
852
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
853
+			require_once(EE_CLASSES . 'EE_Export.class.php');
854
+			$EE_Export = EE_Export::instance($this->_req_data);
855
+			if ($EE_Export instanceof EE_Export) {
856
+				$EE_Export->export();
857
+			}
858
+		}
859
+	}
860
+
861
+
862
+	/**
863
+	 * Creates a sample CSV file for importing
864
+	 */
865
+	protected function _sample_export_file()
866
+	{
867
+		$EE_Export = EE_Export::instance();
868
+		if ($EE_Export instanceof EE_Export) {
869
+			$EE_Export->export();
870
+		}
871
+	}
872
+
873
+
874
+	/*************        Template Settings        *************/
875
+	/**
876
+	 * Generates template settings page output
877
+	 *
878
+	 * @throws DomainException
879
+	 * @throws EE_Error
880
+	 * @throws InvalidArgumentException
881
+	 * @throws InvalidDataTypeException
882
+	 * @throws InvalidInterfaceException
883
+	 */
884
+	protected function _template_settings()
885
+	{
886
+		$this->_template_args['values'] = $this->_yes_no_values;
887
+		/**
888
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
889
+		 * from General_Settings_Admin_Page to here.
890
+		 */
891
+		$this->_template_args = apply_filters(
892
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
893
+			$this->_template_args
894
+		);
895
+		$this->_set_add_edit_form_tags('update_template_settings');
896
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
897
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
898
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
899
+			$this->_template_args,
900
+			true
901
+		);
902
+		$this->display_admin_page_with_sidebar();
903
+	}
904
+
905
+
906
+	/**
907
+	 * Handler for updating template settings.
908
+	 *
909
+	 * @throws EE_Error
910
+	 * @throws InvalidArgumentException
911
+	 * @throws InvalidDataTypeException
912
+	 * @throws InvalidInterfaceException
913
+	 */
914
+	protected function _update_template_settings()
915
+	{
916
+		/**
917
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
918
+		 * from General_Settings_Admin_Page to here.
919
+		 */
920
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
921
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
922
+			EE_Registry::instance()->CFG->template_settings,
923
+			$this->_req_data
924
+		);
925
+		// update custom post type slugs and detect if we need to flush rewrite rules
926
+		$old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
927
+		EE_Registry::instance()->CFG->core->event_cpt_slug = empty($this->_req_data['event_cpt_slug'])
928
+			? EE_Registry::instance()->CFG->core->event_cpt_slug
929
+			: EEH_URL::slugify($this->_req_data['event_cpt_slug'], 'events');
930
+		$what = 'Template Settings';
931
+		$success = $this->_update_espresso_configuration(
932
+			$what,
933
+			EE_Registry::instance()->CFG->template_settings,
934
+			__FILE__,
935
+			__FUNCTION__,
936
+			__LINE__
937
+		);
938
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug !== $old_slug) {
939
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
940
+			$rewrite_rules = LoaderFactory::getLoader()->getShared(
941
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
942
+			);
943
+			$rewrite_rules->flush();
944
+		}
945
+		$this->_redirect_after_action($success, $what, 'updated', array('action' => 'template_settings'));
946
+	}
947
+
948
+
949
+	/**
950
+	 * _premium_event_editor_meta_boxes
951
+	 * add all metaboxes related to the event_editor
952
+	 *
953
+	 * @access protected
954
+	 * @return void
955
+	 * @throws EE_Error
956
+	 * @throws InvalidArgumentException
957
+	 * @throws InvalidDataTypeException
958
+	 * @throws InvalidInterfaceException
959
+	 * @throws ReflectionException
960
+	 */
961
+	protected function _premium_event_editor_meta_boxes()
962
+	{
963
+		$this->verify_cpt_object();
964
+		add_meta_box(
965
+			'espresso_event_editor_event_options',
966
+			esc_html__('Event Registration Options', 'event_espresso'),
967
+			array($this, 'registration_options_meta_box'),
968
+			$this->page_slug,
969
+			'side',
970
+			'core'
971
+		);
972
+	}
973
+
974
+
975
+	/**
976
+	 * override caf metabox
977
+	 *
978
+	 * @return void
979
+	 * @throws DomainException
980
+	 * @throws EE_Error
981
+	 */
982
+	public function registration_options_meta_box()
983
+	{
984
+		$yes_no_values = array(
985
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
986
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
987
+		);
988
+		$default_reg_status_values = EEM_Registration::reg_status_array(
989
+			array(
990
+				EEM_Registration::status_id_cancelled,
991
+				EEM_Registration::status_id_declined,
992
+				EEM_Registration::status_id_incomplete,
993
+				EEM_Registration::status_id_wait_list,
994
+			),
995
+			true
996
+		);
997
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
998
+		$template_args['_event'] = $this->_cpt_model_obj;
999
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1000
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1001
+			'default_reg_status',
1002
+			$default_reg_status_values,
1003
+			$this->_cpt_model_obj->default_registration_status()
1004
+		);
1005
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1006
+			'display_desc',
1007
+			$yes_no_values,
1008
+			$this->_cpt_model_obj->display_description()
1009
+		);
1010
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1011
+			'display_ticket_selector',
1012
+			$yes_no_values,
1013
+			$this->_cpt_model_obj->display_ticket_selector(),
1014
+			'',
1015
+			'',
1016
+			false
1017
+		);
1018
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
1019
+			'EVT_default_registration_status',
1020
+			$default_reg_status_values,
1021
+			$this->_cpt_model_obj->default_registration_status()
1022
+		);
1023
+		$template_args['additional_registration_options'] = apply_filters(
1024
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1025
+			'',
1026
+			$template_args,
1027
+			$yes_no_values,
1028
+			$default_reg_status_values
1029
+		);
1030
+		EEH_Template::display_template(
1031
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
1032
+			$template_args
1033
+		);
1034
+	}
1035
+
1036
+
1037
+
1038
+	/**
1039
+	 * wp_list_table_mods for caf
1040
+	 * ============================
1041
+	 */
1042
+	/**
1043
+	 * hook into list table filters and provide filters for caffeinated list table
1044
+	 *
1045
+	 * @param array $old_filters    any existing filters present
1046
+	 * @param array $list_table_obj the list table object
1047
+	 * @return array                  new filters
1048
+	 * @throws EE_Error
1049
+	 * @throws InvalidArgumentException
1050
+	 * @throws InvalidDataTypeException
1051
+	 * @throws InvalidInterfaceException
1052
+	 * @throws ReflectionException
1053
+	 */
1054
+	public function list_table_filters($old_filters, $list_table_obj)
1055
+	{
1056
+		$filters = array();
1057
+		// first month/year filters
1058
+		$filters[] = $this->espresso_event_months_dropdown();
1059
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1060
+		// active status dropdown
1061
+		if ($status !== 'draft') {
1062
+			$filters[] = $this->active_status_dropdown(
1063
+				isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : ''
1064
+			);
1065
+			$filters[] = $this->venuesDropdown(
1066
+				isset($this->_req_data['venue']) ? $this->_req_data['venue'] : ''
1067
+			);
1068
+		}
1069
+		// category filter
1070
+		$filters[] = $this->category_dropdown();
1071
+		return array_merge($old_filters, $filters);
1072
+	}
1073
+
1074
+
1075
+	/**
1076
+	 * espresso_event_months_dropdown
1077
+	 *
1078
+	 * @access public
1079
+	 * @return string                dropdown listing month/year selections for events.
1080
+	 */
1081
+	public function espresso_event_months_dropdown()
1082
+	{
1083
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
1084
+		// Note we need to include any other filters that are set!
1085
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1086
+		// categories?
1087
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1088
+			? $this->_req_data['EVT_CAT']
1089
+			: null;
1090
+		// active status?
1091
+		$active_status = isset($this->_req_data['active_status']) ? $this->_req_data['active_status'] : null;
1092
+		$cur_date = isset($this->_req_data['month_range']) ? $this->_req_data['month_range'] : '';
1093
+		return EEH_Form_Fields::generate_event_months_dropdown($cur_date, $status, $category, $active_status);
1094
+	}
1095
+
1096
+
1097
+	/**
1098
+	 * returns a list of "active" statuses on the event
1099
+	 *
1100
+	 * @param  string $current_value whatever the current active status is
1101
+	 * @return string
1102
+	 */
1103
+	public function active_status_dropdown($current_value = '')
1104
+	{
1105
+		$select_name = 'active_status';
1106
+		$values = array(
1107
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1108
+			'active'   => esc_html__('Active', 'event_espresso'),
1109
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1110
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1111
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1112
+		);
1113
+
1114
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1115
+	}
1116
+
1117
+
1118
+	/**
1119
+	 * returns a list of "venues"
1120
+	 *
1121
+	 * @param string $current_value whatever the current active status is
1122
+	 * @return string
1123
+	 * @throws EE_Error
1124
+	 * @throws InvalidArgumentException
1125
+	 * @throws InvalidDataTypeException
1126
+	 * @throws InvalidInterfaceException
1127
+	 * @throws ReflectionException
1128
+	 */
1129
+	protected function venuesDropdown($current_value = '')
1130
+	{
1131
+		$select_name = 'venue';
1132
+		$values = array(
1133
+			'' => esc_html__('All Venues', 'event_espresso'),
1134
+		);
1135
+		// populate the list of venues.
1136
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1137
+		$venues = $venue_model->get_all(array('order_by' => array('VNU_name' => 'ASC')));
1138
+
1139
+		foreach ($venues as $venue) {
1140
+			$values[ $venue->ID() ] = $venue->name();
1141
+		}
1142
+
1143
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1144
+	}
1145
+
1146
+
1147
+	/**
1148
+	 * output a dropdown of the categories for the category filter on the event admin list table
1149
+	 *
1150
+	 * @access  public
1151
+	 * @return string html
1152
+	 */
1153
+	public function category_dropdown()
1154
+	{
1155
+		$cur_cat = isset($this->_req_data['EVT_CAT']) ? $this->_req_data['EVT_CAT'] : -1;
1156
+		return EEH_Form_Fields::generate_event_category_dropdown($cur_cat);
1157
+	}
1158
+
1159
+
1160
+	/**
1161
+	 * get total number of events today
1162
+	 *
1163
+	 * @access public
1164
+	 * @return int
1165
+	 * @throws EE_Error
1166
+	 * @throws InvalidArgumentException
1167
+	 * @throws InvalidDataTypeException
1168
+	 * @throws InvalidInterfaceException
1169
+	 */
1170
+	public function total_events_today()
1171
+	{
1172
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1173
+			'DTT_EVT_start',
1174
+			date('Y-m-d') . ' 00:00:00',
1175
+			'Y-m-d H:i:s',
1176
+			'UTC'
1177
+		);
1178
+		$end = EEM_Datetime::instance()->convert_datetime_for_query(
1179
+			'DTT_EVT_start',
1180
+			date('Y-m-d') . ' 23:59:59',
1181
+			'Y-m-d H:i:s',
1182
+			'UTC'
1183
+		);
1184
+		$where = array(
1185
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1186
+		);
1187
+		return EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1188
+	}
1189
+
1190
+
1191
+	/**
1192
+	 * get total number of events this month
1193
+	 *
1194
+	 * @access public
1195
+	 * @return int
1196
+	 * @throws EE_Error
1197
+	 * @throws InvalidArgumentException
1198
+	 * @throws InvalidDataTypeException
1199
+	 * @throws InvalidInterfaceException
1200
+	 */
1201
+	public function total_events_this_month()
1202
+	{
1203
+		// Dates
1204
+		$this_year_r = date('Y');
1205
+		$this_month_r = date('m');
1206
+		$days_this_month = date('t');
1207
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1208
+			'DTT_EVT_start',
1209
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1210
+			'Y-m-d H:i:s',
1211
+			'UTC'
1212
+		);
1213
+		$end = EEM_Datetime::instance()->convert_datetime_for_query(
1214
+			'DTT_EVT_start',
1215
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1216
+			'Y-m-d H:i:s',
1217
+			'UTC'
1218
+		);
1219
+		$where = array(
1220
+			'Datetime.DTT_EVT_start' => array('BETWEEN', array($start, $end)),
1221
+		);
1222
+		return EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
1223
+	}
1224
+
1225
+
1226
+	/** DEFAULT TICKETS STUFF **/
1227
+
1228
+	/**
1229
+	 * Output default tickets list table view.
1230
+	 *
1231
+	 * @throws DomainException
1232
+	 * @throws EE_Error
1233
+	 * @throws InvalidArgumentException
1234
+	 * @throws InvalidDataTypeException
1235
+	 * @throws InvalidInterfaceException
1236
+	 */
1237
+	public function _tickets_overview_list_table()
1238
+	{
1239
+		$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1240
+		$this->display_admin_list_table_page_with_no_sidebar();
1241
+	}
1242
+
1243
+
1244
+	/**
1245
+	 * @param int  $per_page
1246
+	 * @param bool $count
1247
+	 * @param bool $trashed
1248
+	 * @return EE_Soft_Delete_Base_Class[]|int
1249
+	 * @throws EE_Error
1250
+	 * @throws InvalidArgumentException
1251
+	 * @throws InvalidDataTypeException
1252
+	 * @throws InvalidInterfaceException
1253
+	 */
1254
+	public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1255
+	{
1256
+		$orderby = empty($this->_req_data['orderby']) ? 'TKT_name' : $this->_req_data['orderby'];
1257
+		$order = empty($this->_req_data['order']) ? 'ASC' : $this->_req_data['order'];
1258
+		switch ($orderby) {
1259
+			case 'TKT_name':
1260
+				$orderby = array('TKT_name' => $order);
1261
+				break;
1262
+			case 'TKT_price':
1263
+				$orderby = array('TKT_price' => $order);
1264
+				break;
1265
+			case 'TKT_uses':
1266
+				$orderby = array('TKT_uses' => $order);
1267
+				break;
1268
+			case 'TKT_min':
1269
+				$orderby = array('TKT_min' => $order);
1270
+				break;
1271
+			case 'TKT_max':
1272
+				$orderby = array('TKT_max' => $order);
1273
+				break;
1274
+			case 'TKT_qty':
1275
+				$orderby = array('TKT_qty' => $order);
1276
+				break;
1277
+		}
1278
+		$current_page = isset($this->_req_data['paged']) && ! empty($this->_req_data['paged'])
1279
+			? $this->_req_data['paged']
1280
+			: 1;
1281
+		$per_page = isset($this->_req_data['perpage']) && ! empty($this->_req_data['perpage'])
1282
+			? $this->_req_data['perpage']
1283
+			: $per_page;
1284
+		$_where = array(
1285
+			'TKT_is_default' => 1,
1286
+			'TKT_deleted'    => $trashed,
1287
+		);
1288
+		$offset = ($current_page - 1) * $per_page;
1289
+		$limit = array($offset, $per_page);
1290
+		if (isset($this->_req_data['s'])) {
1291
+			$sstr = '%' . $this->_req_data['s'] . '%';
1292
+			$_where['OR'] = array(
1293
+				'TKT_name'        => array('LIKE', $sstr),
1294
+				'TKT_description' => array('LIKE', $sstr),
1295
+			);
1296
+		}
1297
+		$query_params = array(
1298
+			$_where,
1299
+			'order_by' => $orderby,
1300
+			'limit'    => $limit,
1301
+			'group_by' => 'TKT_ID',
1302
+		);
1303
+		if ($count) {
1304
+			return EEM_Ticket::instance()->count_deleted_and_undeleted(array($_where));
1305
+		}
1306
+		return EEM_Ticket::instance()->get_all_deleted_and_undeleted($query_params);
1307
+	}
1308
+
1309
+
1310
+	/**
1311
+	 * @param bool $trash
1312
+	 * @throws EE_Error
1313
+	 * @throws InvalidArgumentException
1314
+	 * @throws InvalidDataTypeException
1315
+	 * @throws InvalidInterfaceException
1316
+	 */
1317
+	protected function _trash_or_restore_ticket($trash = false)
1318
+	{
1319
+		$success = 1;
1320
+		$TKT = EEM_Ticket::instance();
1321
+		// checkboxes?
1322
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1323
+			// if array has more than one element then success message should be plural
1324
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1325
+			// cycle thru the boxes
1326
+			foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1327
+				if ($trash) {
1328
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1329
+						$success = 0;
1330
+					}
1331
+				} elseif (! $TKT->restore_by_ID($TKT_ID)) {
1332
+					$success = 0;
1333
+				}
1334
+			}
1335
+		} else {
1336
+			// grab single id and trash
1337
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1338
+			if ($trash) {
1339
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1340
+					$success = 0;
1341
+				}
1342
+			} elseif (! $TKT->restore_by_ID($TKT_ID)) {
1343
+				$success = 0;
1344
+			}
1345
+		}
1346
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1347
+		$query_args = array(
1348
+			'action' => 'ticket_list_table',
1349
+			'status' => $trash ? '' : 'trashed',
1350
+		);
1351
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1352
+	}
1353
+
1354
+
1355
+	/**
1356
+	 * Handles trashing default ticket.
1357
+	 *
1358
+	 * @throws EE_Error
1359
+	 * @throws InvalidArgumentException
1360
+	 * @throws InvalidDataTypeException
1361
+	 * @throws InvalidInterfaceException
1362
+	 * @throws ReflectionException
1363
+	 */
1364
+	protected function _delete_ticket()
1365
+	{
1366
+		$success = 1;
1367
+		// checkboxes?
1368
+		if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1369
+			// if array has more than one element then success message should be plural
1370
+			$success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1371
+			// cycle thru the boxes
1372
+			foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1373
+				// delete
1374
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1375
+					$success = 0;
1376
+				}
1377
+			}
1378
+		} else {
1379
+			// grab single id and trash
1380
+			$TKT_ID = absint($this->_req_data['TKT_ID']);
1381
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1382
+				$success = 0;
1383
+			}
1384
+		}
1385
+		$action_desc = 'deleted';
1386
+		// fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1387
+		$ticket_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
1388
+			[['TKT_is_default' => 1]],
1389
+			'TKT_ID',
1390
+			true
1391
+		);
1392
+		$query_args = $ticket_count
1393
+			? []
1394
+			: [
1395
+				'action' => 'ticket_list_table',
1396
+				'status' => 'trashed'
1397
+			];
1398
+		$this->_redirect_after_action($success, 'Tickets', $action_desc, $query_args);
1399
+	}
1400
+
1401
+
1402
+	/**
1403
+	 * @param int $TKT_ID
1404
+	 * @return bool|int
1405
+	 * @throws EE_Error
1406
+	 * @throws InvalidArgumentException
1407
+	 * @throws InvalidDataTypeException
1408
+	 * @throws InvalidInterfaceException
1409
+	 * @throws ReflectionException
1410
+	 */
1411
+	protected function _delete_the_ticket($TKT_ID)
1412
+	{
1413
+		$ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1414
+		if (! $ticket instanceof EE_Ticket) {
1415
+			return false;
1416
+		}
1417
+		$ticket->_remove_relations('Datetime');
1418
+		// delete all related prices first
1419
+		$ticket->delete_related_permanently('Price');
1420
+		return $ticket->delete_permanently();
1421
+	}
1422 1422
 }
Please login to merge, or discard this patch.
Spacing   +45 added lines, -45 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
@@ -354,7 +354,7 @@  discard block
 block discarded – undo
354 354
     {
355 355
         wp_register_script(
356 356
             'ee-event-editor-heartbeat',
357
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
357
+            EVENTS_CAF_ASSETS_URL.'event-editor-heartbeat.js',
358 358
             array('ee_admin_js', 'heartbeat'),
359 359
             EVENT_ESPRESSO_VERSION,
360 360
             true
@@ -378,7 +378,7 @@  discard block
 block discarded – undo
378 378
     public function add_additional_datetime_button($template, $template_args)
379 379
     {
380 380
         return EEH_Template::display_template(
381
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
381
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_add_additional_time.template.php',
382 382
             $template_args,
383 383
             true
384 384
         );
@@ -396,7 +396,7 @@  discard block
 block discarded – undo
396 396
     public function add_datetime_clone_button($template, $template_args)
397 397
     {
398 398
         return EEH_Template::display_template(
399
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
399
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_metabox_clone_button.template.php',
400 400
             $template_args,
401 401
             true
402 402
         );
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
     public function datetime_timezones_template($template, $template_args)
415 415
     {
416 416
         return EEH_Template::display_template(
417
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
417
+            EVENTS_CAF_TEMPLATE_PATH.'event_datetime_timezones.template.php',
418 418
             $template_args,
419 419
             true
420 420
         );
@@ -545,7 +545,7 @@  discard block
 block discarded – undo
545 545
     {
546 546
         // first make sure the ID for the event is in the request.
547 547
         //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
548
-        if (! isset($this->_req_data['EVT_ID'])) {
548
+        if ( ! isset($this->_req_data['EVT_ID'])) {
549 549
             EE_Error::add_error(
550 550
                 esc_html__(
551 551
                     'In order to duplicate an event an Event ID is required.  None was given.',
@@ -560,7 +560,7 @@  discard block
 block discarded – undo
560 560
         }
561 561
         // k we've got EVT_ID so let's use that to get the event we'll duplicate
562 562
         $orig_event = EEM_Event::instance()->get_one_by_ID($this->_req_data['EVT_ID']);
563
-        if (! $orig_event instanceof EE_Event) {
563
+        if ( ! $orig_event instanceof EE_Event) {
564 564
             throw new EE_Error(
565 565
                 sprintf(
566 566
                     esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
         $orig_ven = $orig_event->get_many_related('Venue');
577 577
         // reset the ID and modify other details to make it clear this is a dupe
578 578
         $new_event->set('EVT_ID', 0);
579
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
579
+        $new_name = $new_event->name().' '.esc_html__('**DUPLICATE**', 'event_espresso');
580 580
         $new_event->set('EVT_name', $new_name);
581 581
         $new_event->set(
582 582
             'EVT_slug',
@@ -605,7 +605,7 @@  discard block
 block discarded – undo
605 605
             'Question_Group',
606 606
             [['Event_Question_Group.EQG_primary' => true]]
607 607
         );
608
-        if (! empty($orig_primary_qgs)) {
608
+        if ( ! empty($orig_primary_qgs)) {
609 609
             foreach ($orig_primary_qgs as $id => $obj) {
610 610
                 if ($obj instanceof EE_Question_Group) {
611 611
                     $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
@@ -617,7 +617,7 @@  discard block
 block discarded – undo
617 617
             'Question_Group',
618 618
             [['Event_Question_Group.EQG_additional' => true]]
619 619
         );
620
-        if (! empty($orig_additional_qgs)) {
620
+        if ( ! empty($orig_additional_qgs)) {
621 621
             foreach ($orig_additional_qgs as $id => $obj) {
622 622
                 if ($obj instanceof EE_Question_Group) {
623 623
                     $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
@@ -630,7 +630,7 @@  discard block
 block discarded – undo
630 630
         // k now that we have the new event saved we can loop through the datetimes and start adding relations.
631 631
         $cloned_tickets = array();
632 632
         foreach ($orig_datetimes as $orig_dtt) {
633
-            if (! $orig_dtt instanceof EE_Datetime) {
633
+            if ( ! $orig_dtt instanceof EE_Datetime) {
634 634
                 continue;
635 635
             }
636 636
             $new_dtt = clone $orig_dtt;
@@ -645,7 +645,7 @@  discard block
 block discarded – undo
645 645
             // now let's get the ticket relations setup.
646 646
             foreach ((array) $orig_tkts as $orig_tkt) {
647 647
                 // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
648
-                if (! $orig_tkt instanceof EE_Ticket) {
648
+                if ( ! $orig_tkt instanceof EE_Ticket) {
649 649
                     continue;
650 650
                 }
651 651
                 // is this ticket archived?  If it is then let's skip
@@ -654,8 +654,8 @@  discard block
 block discarded – undo
654 654
                 }
655 655
                 // does this original ticket already exist in the clone_tickets cache?
656 656
                 //  If so we'll just use the new ticket from it.
657
-                if (isset($cloned_tickets[ $orig_tkt->ID() ])) {
658
-                    $new_tkt = $cloned_tickets[ $orig_tkt->ID() ];
657
+                if (isset($cloned_tickets[$orig_tkt->ID()])) {
658
+                    $new_tkt = $cloned_tickets[$orig_tkt->ID()];
659 659
                 } else {
660 660
                     $new_tkt = clone $orig_tkt;
661 661
                     // get relations on the $orig_tkt that we need to setup.
@@ -688,7 +688,7 @@  discard block
 block discarded – undo
688 688
                 // for use with later datetimes that have the same ticket.
689 689
                 $new_dtt->_add_relation_to($new_tkt, 'Ticket');
690 690
                 $new_dtt->save();
691
-                $cloned_tickets[ $orig_tkt->ID() ] = $new_tkt;
691
+                $cloned_tickets[$orig_tkt->ID()] = $new_tkt;
692 692
             }
693 693
         }
694 694
         // clone taxonomy information
@@ -775,7 +775,7 @@  discard block
 block discarded – undo
775 775
             $this->_admin_base_url
776 776
         );
777 777
         $content = EEH_Template::display_template(
778
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
778
+            EVENTS_CAF_TEMPLATE_PATH.'import_page.template.php',
779 779
             $this->_template_args,
780 780
             true
781 781
         );
@@ -796,7 +796,7 @@  discard block
 block discarded – undo
796 796
      */
797 797
     protected function _import_events()
798 798
     {
799
-        require_once(EE_CLASSES . 'EE_Import.class.php');
799
+        require_once(EE_CLASSES.'EE_Import.class.php');
800 800
         $success = EE_Import::instance()->import();
801 801
         $this->_redirect_after_action($success, 'Import File', 'ran', array('action' => 'import_page'), true);
802 802
     }
@@ -825,8 +825,8 @@  discard block
 block discarded – undo
825 825
             'EVT_ID' => $event_ids,
826 826
         );
827 827
         $this->_req_data = array_merge($this->_req_data, $new_request_args);
828
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
829
-            require_once(EE_CLASSES . 'EE_Export.class.php');
828
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
829
+            require_once(EE_CLASSES.'EE_Export.class.php');
830 830
             $EE_Export = EE_Export::instance($this->_req_data);
831 831
             if ($EE_Export instanceof EE_Export) {
832 832
                 $EE_Export->export();
@@ -849,8 +849,8 @@  discard block
 block discarded – undo
849 849
             'category_ids' => $this->_req_data['EVT_CAT_ID'],
850 850
         );
851 851
         $this->_req_data = array_merge($this->_req_data, $new_request_args);
852
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
853
-            require_once(EE_CLASSES . 'EE_Export.class.php');
852
+        if (is_readable(EE_CLASSES.'EE_Export.class.php')) {
853
+            require_once(EE_CLASSES.'EE_Export.class.php');
854 854
             $EE_Export = EE_Export::instance($this->_req_data);
855 855
             if ($EE_Export instanceof EE_Export) {
856 856
                 $EE_Export->export();
@@ -895,7 +895,7 @@  discard block
 block discarded – undo
895 895
         $this->_set_add_edit_form_tags('update_template_settings');
896 896
         $this->_set_publish_post_box_vars(null, false, false, null, false);
897 897
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
898
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
898
+            EVENTS_CAF_TEMPLATE_PATH.'template_settings.template.php',
899 899
             $this->_template_args,
900 900
             true
901 901
         );
@@ -1028,7 +1028,7 @@  discard block
 block discarded – undo
1028 1028
             $default_reg_status_values
1029 1029
         );
1030 1030
         EEH_Template::display_template(
1031
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
1031
+            EVENTS_CAF_TEMPLATE_PATH.'event_registration_options.template.php',
1032 1032
             $template_args
1033 1033
         );
1034 1034
     }
@@ -1137,7 +1137,7 @@  discard block
 block discarded – undo
1137 1137
         $venues = $venue_model->get_all(array('order_by' => array('VNU_name' => 'ASC')));
1138 1138
 
1139 1139
         foreach ($venues as $venue) {
1140
-            $values[ $venue->ID() ] = $venue->name();
1140
+            $values[$venue->ID()] = $venue->name();
1141 1141
         }
1142 1142
 
1143 1143
         return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
@@ -1171,13 +1171,13 @@  discard block
 block discarded – undo
1171 1171
     {
1172 1172
         $start = EEM_Datetime::instance()->convert_datetime_for_query(
1173 1173
             'DTT_EVT_start',
1174
-            date('Y-m-d') . ' 00:00:00',
1174
+            date('Y-m-d').' 00:00:00',
1175 1175
             'Y-m-d H:i:s',
1176 1176
             'UTC'
1177 1177
         );
1178 1178
         $end = EEM_Datetime::instance()->convert_datetime_for_query(
1179 1179
             'DTT_EVT_start',
1180
-            date('Y-m-d') . ' 23:59:59',
1180
+            date('Y-m-d').' 23:59:59',
1181 1181
             'Y-m-d H:i:s',
1182 1182
             'UTC'
1183 1183
         );
@@ -1206,13 +1206,13 @@  discard block
 block discarded – undo
1206 1206
         $days_this_month = date('t');
1207 1207
         $start = EEM_Datetime::instance()->convert_datetime_for_query(
1208 1208
             'DTT_EVT_start',
1209
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1209
+            $this_year_r.'-'.$this_month_r.'-01 00:00:00',
1210 1210
             'Y-m-d H:i:s',
1211 1211
             'UTC'
1212 1212
         );
1213 1213
         $end = EEM_Datetime::instance()->convert_datetime_for_query(
1214 1214
             'DTT_EVT_start',
1215
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1215
+            $this_year_r.'-'.$this_month_r.'-'.$days_this_month.' 23:59:59',
1216 1216
             'Y-m-d H:i:s',
1217 1217
             'UTC'
1218 1218
         );
@@ -1288,7 +1288,7 @@  discard block
 block discarded – undo
1288 1288
         $offset = ($current_page - 1) * $per_page;
1289 1289
         $limit = array($offset, $per_page);
1290 1290
         if (isset($this->_req_data['s'])) {
1291
-            $sstr = '%' . $this->_req_data['s'] . '%';
1291
+            $sstr = '%'.$this->_req_data['s'].'%';
1292 1292
             $_where['OR'] = array(
1293 1293
                 'TKT_name'        => array('LIKE', $sstr),
1294 1294
                 'TKT_description' => array('LIKE', $sstr),
@@ -1319,16 +1319,16 @@  discard block
 block discarded – undo
1319 1319
         $success = 1;
1320 1320
         $TKT = EEM_Ticket::instance();
1321 1321
         // checkboxes?
1322
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1322
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1323 1323
             // if array has more than one element then success message should be plural
1324 1324
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1325 1325
             // cycle thru the boxes
1326 1326
             foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1327 1327
                 if ($trash) {
1328
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1328
+                    if ( ! $TKT->delete_by_ID($TKT_ID)) {
1329 1329
                         $success = 0;
1330 1330
                     }
1331
-                } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1331
+                } elseif ( ! $TKT->restore_by_ID($TKT_ID)) {
1332 1332
                     $success = 0;
1333 1333
                 }
1334 1334
             }
@@ -1336,10 +1336,10 @@  discard block
 block discarded – undo
1336 1336
             // grab single id and trash
1337 1337
             $TKT_ID = absint($this->_req_data['TKT_ID']);
1338 1338
             if ($trash) {
1339
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1339
+                if ( ! $TKT->delete_by_ID($TKT_ID)) {
1340 1340
                     $success = 0;
1341 1341
                 }
1342
-            } elseif (! $TKT->restore_by_ID($TKT_ID)) {
1342
+            } elseif ( ! $TKT->restore_by_ID($TKT_ID)) {
1343 1343
                 $success = 0;
1344 1344
             }
1345 1345
         }
@@ -1365,20 +1365,20 @@  discard block
 block discarded – undo
1365 1365
     {
1366 1366
         $success = 1;
1367 1367
         // checkboxes?
1368
-        if (! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1368
+        if ( ! empty($this->_req_data['checkbox']) && is_array($this->_req_data['checkbox'])) {
1369 1369
             // if array has more than one element then success message should be plural
1370 1370
             $success = count($this->_req_data['checkbox']) > 1 ? 2 : 1;
1371 1371
             // cycle thru the boxes
1372 1372
             foreach ($this->_req_data['checkbox'] as $TKT_ID) {
1373 1373
                 // delete
1374
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1374
+                if ( ! $this->_delete_the_ticket($TKT_ID)) {
1375 1375
                     $success = 0;
1376 1376
                 }
1377 1377
             }
1378 1378
         } else {
1379 1379
             // grab single id and trash
1380 1380
             $TKT_ID = absint($this->_req_data['TKT_ID']);
1381
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1381
+            if ( ! $this->_delete_the_ticket($TKT_ID)) {
1382 1382
                 $success = 0;
1383 1383
             }
1384 1384
         }
@@ -1411,7 +1411,7 @@  discard block
 block discarded – undo
1411 1411
     protected function _delete_the_ticket($TKT_ID)
1412 1412
     {
1413 1413
         $ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1414
-        if (! $ticket instanceof EE_Ticket) {
1414
+        if ( ! $ticket instanceof EE_Ticket) {
1415 1415
             return false;
1416 1416
         }
1417 1417
         $ticket->_remove_relations('Datetime');
Please login to merge, or discard this patch.