Completed
Branch fix/event-slug-settings (1f4b8e)
by
unknown
03:26 queued 10s
created
caffeinated/admin/extend/events/Extend_Events_Admin_Page.core.php 1 patch
Indentation   +1304 added lines, -1304 removed lines patch added patch discarded remove patch
@@ -14,1308 +14,1308 @@
 block discarded – undo
14 14
 {
15 15
 
16 16
 
17
-    /**
18
-     * Extend_Events_Admin_Page constructor.
19
-     *
20
-     * @param bool $routing
21
-     * @throws EE_Error
22
-     * @throws ReflectionException
23
-     */
24
-    public function __construct($routing = true)
25
-    {
26
-        parent::__construct($routing);
27
-        if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
28
-            define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
29
-            define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
30
-            define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
31
-        }
32
-    }
33
-
34
-
35
-    /**
36
-     * Sets routes.
37
-     *
38
-     * @throws EE_Error
39
-     */
40
-    protected function _extend_page_config()
41
-    {
42
-        $this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
43
-        // is there a evt_id in the request?
44
-        $EVT_ID             = $this->request->getRequestParam('EVT_ID', 0, 'int');
45
-        $EVT_ID             = $this->request->getRequestParam('post', $EVT_ID, 'int');
46
-        $TKT_ID             = $this->request->getRequestParam('TKT_ID', 0, 'int');
47
-        $new_page_routes    = [
48
-            'duplicate_event'          => [
49
-                'func'       => '_duplicate_event',
50
-                'capability' => 'ee_edit_event',
51
-                'obj_id'     => $EVT_ID,
52
-                'noheader'   => true,
53
-            ],
54
-            'ticket_list_table'        => [
55
-                'func'       => '_tickets_overview_list_table',
56
-                'capability' => 'ee_read_default_tickets',
57
-            ],
58
-            'trash_ticket'             => [
59
-                'func'       => '_trash_or_restore_ticket',
60
-                'capability' => 'ee_delete_default_ticket',
61
-                'obj_id'     => $TKT_ID,
62
-                'noheader'   => true,
63
-                'args'       => ['trash' => true],
64
-            ],
65
-            'trash_tickets'            => [
66
-                'func'       => '_trash_or_restore_ticket',
67
-                'capability' => 'ee_delete_default_tickets',
68
-                'noheader'   => true,
69
-                'args'       => ['trash' => true],
70
-            ],
71
-            'restore_ticket'           => [
72
-                'func'       => '_trash_or_restore_ticket',
73
-                'capability' => 'ee_delete_default_ticket',
74
-                'obj_id'     => $TKT_ID,
75
-                'noheader'   => true,
76
-            ],
77
-            'restore_tickets'          => [
78
-                'func'       => '_trash_or_restore_ticket',
79
-                'capability' => 'ee_delete_default_tickets',
80
-                'noheader'   => true,
81
-            ],
82
-            'delete_ticket'            => [
83
-                'func'       => '_delete_ticket',
84
-                'capability' => 'ee_delete_default_ticket',
85
-                'obj_id'     => $TKT_ID,
86
-                'noheader'   => true,
87
-            ],
88
-            'delete_tickets'           => [
89
-                'func'       => '_delete_ticket',
90
-                'capability' => 'ee_delete_default_tickets',
91
-                'noheader'   => true,
92
-            ],
93
-            'import_page'              => [
94
-                'func'       => '_import_page',
95
-                'capability' => 'import',
96
-            ],
97
-            'import'                   => [
98
-                'func'       => '_import_events',
99
-                'capability' => 'import',
100
-                'noheader'   => true,
101
-            ],
102
-            'import_events'            => [
103
-                'func'       => '_import_events',
104
-                'capability' => 'import',
105
-                'noheader'   => true,
106
-            ],
107
-            'export_events'            => [
108
-                'func'       => '_events_export',
109
-                'capability' => 'export',
110
-                'noheader'   => true,
111
-            ],
112
-            'export_categories'        => [
113
-                'func'       => '_categories_export',
114
-                'capability' => 'export',
115
-                'noheader'   => true,
116
-            ],
117
-            'sample_export_file'       => [
118
-                'func'       => '_sample_export_file',
119
-                'capability' => 'export',
120
-                'noheader'   => true,
121
-            ],
122
-            'update_template_settings' => [
123
-                'func'       => '_update_template_settings',
124
-                'capability' => 'manage_options',
125
-                'noheader'   => true,
126
-            ],
127
-        ];
128
-        $this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
129
-        // partial route/config override
130
-        $this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
131
-        $this->_page_config['create_new']['metaboxes'][]  = '_premium_event_editor_meta_boxes';
132
-        $this->_page_config['create_new']['qtips'][]      = 'EE_Event_Editor_Tips';
133
-        $this->_page_config['edit']['qtips'][]            = 'EE_Event_Editor_Tips';
134
-        $this->_page_config['edit']['metaboxes'][]        = '_premium_event_editor_meta_boxes';
135
-        $this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
136
-        // add tickets tab but only if there are more than one default ticket!
137
-        $ticket_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
138
-            [['TKT_is_default' => 1]],
139
-            'TKT_ID',
140
-            true
141
-        );
142
-        if ($ticket_count > 1) {
143
-            $new_page_config = [
144
-                'ticket_list_table' => [
145
-                    'nav'           => [
146
-                        'label' => esc_html__('Default Tickets', 'event_espresso'),
147
-                        'order' => 60,
148
-                    ],
149
-                    'list_table'    => 'Tickets_List_Table',
150
-                    'require_nonce' => false,
151
-                ],
152
-            ];
153
-        }
154
-        // template settings
155
-        $new_page_config['template_settings'] = [
156
-            'nav'           => [
157
-                'label' => esc_html__('Templates', 'event_espresso'),
158
-                'order' => 30,
159
-            ],
160
-            'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
161
-            'help_tabs'     => [
162
-                'general_settings_templates_help_tab' => [
163
-                    'title'    => esc_html__('Templates', 'event_espresso'),
164
-                    'filename' => 'general_settings_templates',
165
-                ],
166
-            ],
167
-            // disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
168
-            // 'help_tour'     => array('Templates_Help_Tour'),
169
-            'require_nonce' => false,
170
-        ];
171
-        $this->_page_config                   = array_merge($this->_page_config, $new_page_config);
172
-        // add filters and actions
173
-        // modifying _views
174
-        add_filter(
175
-            'FHEE_event_datetime_metabox_add_additional_date_time_template',
176
-            [$this, 'add_additional_datetime_button'],
177
-            10,
178
-            2
179
-        );
180
-        add_filter(
181
-            'FHEE_event_datetime_metabox_clone_button_template',
182
-            [$this, 'add_datetime_clone_button'],
183
-            10,
184
-            2
185
-        );
186
-        add_filter(
187
-            'FHEE_event_datetime_metabox_timezones_template',
188
-            [$this, 'datetime_timezones_template'],
189
-            10,
190
-            2
191
-        );
192
-        // filters for event list table
193
-        add_filter('FHEE__Extend_Events_Admin_List_Table__filters', [$this, 'list_table_filters'], 10, 2);
194
-        add_filter(
195
-            'FHEE__Events_Admin_List_Table__column_actions__action_links',
196
-            [$this, 'extra_list_table_actions'],
197
-            10,
198
-            2
199
-        );
200
-        // legend item
201
-        add_filter('FHEE__Events_Admin_Page___event_legend_items__items', [$this, 'additional_legend_items']);
202
-        add_action('admin_init', [$this, 'admin_init']);
203
-    }
204
-
205
-
206
-    /**
207
-     * admin_init
208
-     */
209
-    public function admin_init()
210
-    {
211
-        EE_Registry::$i18n_js_strings = array_merge(
212
-            EE_Registry::$i18n_js_strings,
213
-            [
214
-                'image_confirm'          => esc_html__(
215
-                    'Do you really want to delete this image? Please remember to update your event to complete the removal.',
216
-                    'event_espresso'
217
-                ),
218
-                'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
219
-                'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
220
-                'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
221
-                'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
222
-                'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
223
-            ]
224
-        );
225
-    }
226
-
227
-
228
-    /**
229
-     * Add per page screen options to the default ticket list table view.
230
-     */
231
-    protected function _add_screen_options_ticket_list_table()
232
-    {
233
-        $this->_per_page_screen_option();
234
-    }
235
-
236
-
237
-    /**
238
-     * @param string $return
239
-     * @param int    $id
240
-     * @param string $new_title
241
-     * @param string $new_slug
242
-     * @return string
243
-     */
244
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
245
-    {
246
-        $return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
247
-        // make sure this is only when editing
248
-        if (! empty($id)) {
249
-            $href   = EE_Admin_Page::add_query_args_and_nonce(
250
-                ['action' => 'duplicate_event', 'EVT_ID' => $id],
251
-                $this->_admin_base_url
252
-            );
253
-            $title  = esc_attr__('Duplicate Event', 'event_espresso');
254
-            $return .= '<a href="'
255
-                       . $href
256
-                       . '" title="'
257
-                       . $title
258
-                       . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
259
-                       . $title
260
-                       . '</a>';
261
-        }
262
-        return $return;
263
-    }
264
-
265
-
266
-    /**
267
-     * Set the list table views for the default ticket list table view.
268
-     */
269
-    public function _set_list_table_views_ticket_list_table()
270
-    {
271
-        $this->_views = [
272
-            'all'     => [
273
-                'slug'        => 'all',
274
-                'label'       => esc_html__('All', 'event_espresso'),
275
-                'count'       => 0,
276
-                'bulk_action' => [
277
-                    'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
278
-                ],
279
-            ],
280
-            'trashed' => [
281
-                'slug'        => 'trashed',
282
-                'label'       => esc_html__('Trash', 'event_espresso'),
283
-                'count'       => 0,
284
-                'bulk_action' => [
285
-                    'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
286
-                    'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
287
-                ],
288
-            ],
289
-        ];
290
-    }
291
-
292
-
293
-    /**
294
-     * Enqueue scripts and styles for the event editor.
295
-     */
296
-    public function load_scripts_styles_edit()
297
-    {
298
-        wp_register_script(
299
-            'ee-event-editor-heartbeat',
300
-            EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
301
-            ['ee_admin_js', 'heartbeat'],
302
-            EVENT_ESPRESSO_VERSION,
303
-            true
304
-        );
305
-        wp_enqueue_script('ee-accounting');
306
-        // styles
307
-        wp_enqueue_style('espresso-ui-theme');
308
-        wp_enqueue_script('event_editor_js');
309
-        wp_enqueue_script('ee-event-editor-heartbeat');
310
-    }
311
-
312
-
313
-    /**
314
-     * Returns template for the additional datetime.
315
-     *
316
-     * @param string $template
317
-     * @param array  $template_args
318
-     * @return string
319
-     * @throws DomainException
320
-     */
321
-    public function add_additional_datetime_button($template, $template_args)
322
-    {
323
-        return EEH_Template::display_template(
324
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
325
-            $template_args,
326
-            true
327
-        );
328
-    }
329
-
330
-
331
-    /**
332
-     * Returns the template for cloning a datetime.
333
-     *
334
-     * @param $template
335
-     * @param $template_args
336
-     * @return string
337
-     * @throws DomainException
338
-     */
339
-    public function add_datetime_clone_button($template, $template_args)
340
-    {
341
-        return EEH_Template::display_template(
342
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
343
-            $template_args,
344
-            true
345
-        );
346
-    }
347
-
348
-
349
-    /**
350
-     * Returns the template for datetime timezones.
351
-     *
352
-     * @param $template
353
-     * @param $template_args
354
-     * @return string
355
-     * @throws DomainException
356
-     */
357
-    public function datetime_timezones_template($template, $template_args)
358
-    {
359
-        return EEH_Template::display_template(
360
-            EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
361
-            $template_args,
362
-            true
363
-        );
364
-    }
365
-
366
-
367
-    /**
368
-     * Sets the views for the default list table view.
369
-     *
370
-     * @throws EE_Error
371
-     */
372
-    protected function _set_list_table_views_default()
373
-    {
374
-        parent::_set_list_table_views_default();
375
-        $new_views    = [
376
-            'today' => [
377
-                'slug'        => 'today',
378
-                'label'       => esc_html__('Today', 'event_espresso'),
379
-                'count'       => $this->total_events_today(),
380
-                'bulk_action' => [
381
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
382
-                ],
383
-            ],
384
-            'month' => [
385
-                'slug'        => 'month',
386
-                'label'       => esc_html__('This Month', 'event_espresso'),
387
-                'count'       => $this->total_events_this_month(),
388
-                'bulk_action' => [
389
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
390
-                ],
391
-            ],
392
-        ];
393
-        $this->_views = array_merge($this->_views, $new_views);
394
-    }
395
-
396
-
397
-    /**
398
-     * Returns the extra action links for the default list table view.
399
-     *
400
-     * @param array    $action_links
401
-     * @param EE_Event $event
402
-     * @return array
403
-     * @throws EE_Error
404
-     * @throws ReflectionException
405
-     */
406
-    public function extra_list_table_actions(array $action_links, EE_Event $event)
407
-    {
408
-        if (
409
-            EE_Registry::instance()->CAP->current_user_can(
410
-                'ee_read_registrations',
411
-                'espresso_registrations_reports',
412
-                $event->ID()
413
-            )
414
-        ) {
415
-            $reports_query_args = [
416
-                'action' => 'reports',
417
-                'EVT_ID' => $event->ID(),
418
-            ];
419
-            $reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
420
-            $action_links[]     = '<a href="'
421
-                                  . $reports_link
422
-                                  . '" title="'
423
-                                  . esc_attr__('View Report', 'event_espresso')
424
-                                  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
425
-                                  . "\n\t";
426
-        }
427
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
428
-            EE_Registry::instance()->load_helper('MSG_Template');
429
-            $action_links[] = EEH_MSG_Template::get_message_action_link(
430
-                'see_notifications_for',
431
-                null,
432
-                ['EVT_ID' => $event->ID()]
433
-            );
434
-        }
435
-        return $action_links;
436
-    }
437
-
438
-
439
-    /**
440
-     * @param $items
441
-     * @return mixed
442
-     */
443
-    public function additional_legend_items($items)
444
-    {
445
-        if (
446
-            EE_Registry::instance()->CAP->current_user_can(
447
-                'ee_read_registrations',
448
-                'espresso_registrations_reports'
449
-            )
450
-        ) {
451
-            $items['reports'] = [
452
-                'class' => 'dashicons dashicons-chart-bar',
453
-                'desc'  => esc_html__('Event Reports', 'event_espresso'),
454
-            ];
455
-        }
456
-        if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
457
-            $related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
458
-            if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
459
-                $items['view_related_messages'] = [
460
-                    'class' => $related_for_icon['css_class'],
461
-                    'desc'  => $related_for_icon['label'],
462
-                ];
463
-            }
464
-        }
465
-        return $items;
466
-    }
467
-
468
-
469
-    /**
470
-     * This is the callback method for the duplicate event route
471
-     * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
472
-     * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
473
-     * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
474
-     * After duplication the redirect is to the new event edit page.
475
-     *
476
-     * @return void
477
-     * @throws EE_Error If EE_Event is not available with given ID
478
-     * @throws ReflectionException
479
-     * @access protected
480
-     */
481
-    protected function _duplicate_event()
482
-    {
483
-        // first make sure the ID for the event is in the request.
484
-        //  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
485
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
486
-        if (! $EVT_ID) {
487
-            EE_Error::add_error(
488
-                esc_html__(
489
-                    'In order to duplicate an event an Event ID is required.  None was given.',
490
-                    'event_espresso'
491
-                ),
492
-                __FILE__,
493
-                __FUNCTION__,
494
-                __LINE__
495
-            );
496
-            $this->_redirect_after_action(false, '', '', [], true);
497
-            return;
498
-        }
499
-        // k we've got EVT_ID so let's use that to get the event we'll duplicate
500
-        $orig_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
501
-        if (! $orig_event instanceof EE_Event) {
502
-            throw new EE_Error(
503
-                sprintf(
504
-                    esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
505
-                    $EVT_ID
506
-                )
507
-            );
508
-        }
509
-        // k now let's clone the $orig_event before getting relations
510
-        $new_event = clone $orig_event;
511
-        // original datetimes
512
-        $orig_datetimes = $orig_event->get_many_related('Datetime');
513
-        // other original relations
514
-        $orig_ven = $orig_event->get_many_related('Venue');
515
-        // reset the ID and modify other details to make it clear this is a dupe
516
-        $new_event->set('EVT_ID', 0);
517
-        $new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
518
-        $new_event->set('EVT_name', $new_name);
519
-        $new_event->set(
520
-            'EVT_slug',
521
-            wp_unique_post_slug(
522
-                sanitize_title($orig_event->name()),
523
-                0,
524
-                'publish',
525
-                'espresso_events',
526
-                0
527
-            )
528
-        );
529
-        $new_event->set('status', 'draft');
530
-        // duplicate discussion settings
531
-        $new_event->set('comment_status', $orig_event->get('comment_status'));
532
-        $new_event->set('ping_status', $orig_event->get('ping_status'));
533
-        // save the new event
534
-        $new_event->save();
535
-        // venues
536
-        foreach ($orig_ven as $ven) {
537
-            $new_event->_add_relation_to($ven, 'Venue');
538
-        }
539
-        $new_event->save();
540
-        // now we need to get the question group relations and handle that
541
-        // first primary question groups
542
-        $orig_primary_qgs = $orig_event->get_many_related(
543
-            'Question_Group',
544
-            [['Event_Question_Group.EQG_primary' => true]]
545
-        );
546
-        if (! empty($orig_primary_qgs)) {
547
-            foreach ($orig_primary_qgs as $obj) {
548
-                if ($obj instanceof EE_Question_Group) {
549
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
550
-                }
551
-            }
552
-        }
553
-        // next additional attendee question groups
554
-        $orig_additional_qgs = $orig_event->get_many_related(
555
-            'Question_Group',
556
-            [['Event_Question_Group.EQG_additional' => true]]
557
-        );
558
-        if (! empty($orig_additional_qgs)) {
559
-            foreach ($orig_additional_qgs as $obj) {
560
-                if ($obj instanceof EE_Question_Group) {
561
-                    $new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
562
-                }
563
-            }
564
-        }
565
-
566
-        $new_event->save();
567
-
568
-        // k now that we have the new event saved we can loop through the datetimes and start adding relations.
569
-        $cloned_tickets = [];
570
-        foreach ($orig_datetimes as $orig_dtt) {
571
-            if (! $orig_dtt instanceof EE_Datetime) {
572
-                continue;
573
-            }
574
-            $new_dtt      = clone $orig_dtt;
575
-            $orig_tickets = $orig_dtt->tickets();
576
-            // save new dtt then add to event
577
-            $new_dtt->set('DTT_ID', 0);
578
-            $new_dtt->set('DTT_sold', 0);
579
-            $new_dtt->set_reserved(0);
580
-            $new_dtt->save();
581
-            $new_event->_add_relation_to($new_dtt, 'Datetime');
582
-            $new_event->save();
583
-            // now let's get the ticket relations setup.
584
-            foreach ((array) $orig_tickets as $orig_ticket) {
585
-                // it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
586
-                if (! $orig_ticket instanceof EE_Ticket) {
587
-                    continue;
588
-                }
589
-                // is this ticket archived?  If it is then let's skip
590
-                if ($orig_ticket->get('TKT_deleted')) {
591
-                    continue;
592
-                }
593
-                // does this original ticket already exist in the clone_tickets cache?
594
-                //  If so we'll just use the new ticket from it.
595
-                if (isset($cloned_tickets[ $orig_ticket->ID() ])) {
596
-                    $new_ticket = $cloned_tickets[ $orig_ticket->ID() ];
597
-                } else {
598
-                    $new_ticket = clone $orig_ticket;
599
-                    // get relations on the $orig_ticket that we need to setup.
600
-                    $orig_prices = $orig_ticket->prices();
601
-                    $new_ticket->set('TKT_ID', 0);
602
-                    $new_ticket->set('TKT_sold', 0);
603
-                    $new_ticket->set('TKT_reserved', 0);
604
-                    $new_ticket->save(); // make sure new ticket has ID.
605
-                    // price relations on new ticket need to be setup.
606
-                    foreach ($orig_prices as $orig_price) {
607
-                        $new_price = clone $orig_price;
608
-                        $new_price->set('PRC_ID', 0);
609
-                        $new_price->save();
610
-                        $new_ticket->_add_relation_to($new_price, 'Price');
611
-                        $new_ticket->save();
612
-                    }
613
-
614
-                    do_action(
615
-                        'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
616
-                        $orig_ticket,
617
-                        $new_ticket,
618
-                        $orig_prices,
619
-                        $orig_event,
620
-                        $orig_dtt,
621
-                        $new_dtt
622
-                    );
623
-                }
624
-                // k now we can add the new ticket as a relation to the new datetime
625
-                // and make sure its added to our cached $cloned_tickets array
626
-                // for use with later datetimes that have the same ticket.
627
-                $new_dtt->_add_relation_to($new_ticket, 'Ticket');
628
-                $new_dtt->save();
629
-                $cloned_tickets[ $orig_ticket->ID() ] = $new_ticket;
630
-            }
631
-        }
632
-        // clone taxonomy information
633
-        $taxonomies_to_clone_with = apply_filters(
634
-            'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
635
-            ['espresso_event_categories', 'espresso_event_type', 'post_tag']
636
-        );
637
-        // get terms for original event (notice)
638
-        $orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
639
-        // loop through terms and add them to new event.
640
-        foreach ($orig_terms as $term) {
641
-            wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
642
-        }
643
-
644
-        // duplicate other core WP_Post items for this event.
645
-        // post thumbnail (feature image).
646
-        $feature_image_id = get_post_thumbnail_id($orig_event->ID());
647
-        if ($feature_image_id) {
648
-            update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
649
-        }
650
-
651
-        // duplicate page_template setting
652
-        $page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
653
-        if ($page_template) {
654
-            update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
655
-        }
656
-
657
-        do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
658
-        // now let's redirect to the edit page for this duplicated event if we have a new event id.
659
-        if ($new_event->ID()) {
660
-            $redirect_args = [
661
-                'post'   => $new_event->ID(),
662
-                'action' => 'edit',
663
-            ];
664
-            EE_Error::add_success(
665
-                esc_html__(
666
-                    'Event successfully duplicated.  Please review the details below and make any necessary edits',
667
-                    'event_espresso'
668
-                )
669
-            );
670
-        } else {
671
-            $redirect_args = [
672
-                'action' => 'default',
673
-            ];
674
-            EE_Error::add_error(
675
-                esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
676
-                __FILE__,
677
-                __FUNCTION__,
678
-                __LINE__
679
-            );
680
-        }
681
-        $this->_redirect_after_action(false, '', '', $redirect_args, true);
682
-    }
683
-
684
-
685
-    /**
686
-     * Generates output for the import page.
687
-     *
688
-     * @throws EE_Error
689
-     */
690
-    protected function _import_page()
691
-    {
692
-        $title = esc_html__('Import', 'event_espresso');
693
-        $intro = esc_html__(
694
-            'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
695
-            'event_espresso'
696
-        );
697
-
698
-        $form_url = EVENTS_ADMIN_URL;
699
-        $action   = 'import_events';
700
-        $type     = 'csv';
701
-
702
-        $this->_template_args['form'] = EE_Import::instance()->upload_form(
703
-            $title,
704
-            $intro,
705
-            $form_url,
706
-            $action,
707
-            $type
708
-        );
709
-
710
-        $this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
711
-            ['action' => 'sample_export_file'],
712
-            $this->_admin_base_url
713
-        );
714
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
715
-            EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
716
-            $this->_template_args,
717
-            true
718
-        );
719
-        $this->display_admin_page_with_sidebar();
720
-    }
721
-
722
-
723
-    /**
724
-     * _import_events
725
-     * This handles displaying the screen and running imports for importing events.
726
-     *
727
-     * @return void
728
-     * @throws EE_Error
729
-     */
730
-    protected function _import_events()
731
-    {
732
-        require_once(EE_CLASSES . 'EE_Import.class.php');
733
-        $success = EE_Import::instance()->import();
734
-        $this->_redirect_after_action(
735
-            $success,
736
-            esc_html__('Import File', 'event_espresso'),
737
-            'ran',
738
-            ['action' => 'import_page'],
739
-            true
740
-        );
741
-    }
742
-
743
-
744
-    /**
745
-     * _events_export
746
-     * Will export all (or just the given event) to a Excel compatible file.
747
-     *
748
-     * @access protected
749
-     * @return void
750
-     */
751
-    protected function _events_export()
752
-    {
753
-        $EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
754
-        $EVT_ID = $this->request->getRequestParam('EVT_IDs', $EVT_ID, 'int');
755
-        $this->request->mergeRequestParams(
756
-            [
757
-                'export' => 'report',
758
-                'action' => 'all_event_data',
759
-                'EVT_ID' => $EVT_ID,
760
-            ]
761
-        );
762
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
763
-            require_once(EE_CLASSES . 'EE_Export.class.php');
764
-            $EE_Export = EE_Export::instance($this->request->requestParams());
765
-            $EE_Export->export();
766
-        }
767
-    }
768
-
769
-
770
-    /**
771
-     * handle category exports()
772
-     *
773
-     * @return void
774
-     */
775
-    protected function _categories_export()
776
-    {
777
-        $EVT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
778
-        $this->request->mergeRequestParams(
779
-            [
780
-                'export' => 'report',
781
-                'action' => 'categories',
782
-                'EVT_ID' => $EVT_ID,
783
-            ]
784
-        );
785
-        if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
786
-            require_once(EE_CLASSES . 'EE_Export.class.php');
787
-            $EE_Export = EE_Export::instance($this->request->requestParams());
788
-            $EE_Export->export();
789
-        }
790
-    }
791
-
792
-
793
-    /**
794
-     * Creates a sample CSV file for importing
795
-     */
796
-    protected function _sample_export_file()
797
-    {
798
-        // require_once(EE_CLASSES . 'EE_Export.class.php');
799
-        EE_Export::instance()->export_sample();
800
-    }
801
-
802
-
803
-    /*************        Template Settings        *************/
804
-    /**
805
-     * Generates template settings page output
806
-     *
807
-     * @throws DomainException
808
-     * @throws EE_Error
809
-     */
810
-    protected function _template_settings()
811
-    {
812
-        $this->_template_args['values'] = $this->_yes_no_values;
813
-        /**
814
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
815
-         * from General_Settings_Admin_Page to here.
816
-         */
817
-        $this->_template_args = apply_filters(
818
-            'FHEE__General_Settings_Admin_Page__template_settings__template_args',
819
-            $this->_template_args
820
-        );
821
-        $this->_set_add_edit_form_tags('update_template_settings');
822
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
823
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
824
-            EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
825
-            $this->_template_args,
826
-            true
827
-        );
828
-        $this->display_admin_page_with_sidebar();
829
-    }
830
-
831
-
832
-    /**
833
-     * Handler for updating template settings.
834
-     *
835
-     * @throws EE_Error
836
-     */
837
-    protected function _update_template_settings()
838
-    {
839
-        /**
840
-         * Note leaving this filter in for backward compatibility this was moved in 4.6.x
841
-         * from General_Settings_Admin_Page to here.
842
-         */
843
-        EE_Registry::instance()->CFG->template_settings = apply_filters(
844
-            'FHEE__General_Settings_Admin_Page__update_template_settings__data',
845
-            EE_Registry::instance()->CFG->template_settings,
846
-            $this->request->requestParams()
847
-        );
848
-        // update custom post type slugs and detect if we need to flush rewrite rules
849
-        $old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
850
-
851
-        $event_cpt_slug = $this->request->getRequestParam('event_cpt_slug');
852
-
853
-        EE_Registry::instance()->CFG->core->event_cpt_slug = $event_cpt_slug
854
-            ? EEH_URL::slugify($event_cpt_slug, 'events')
855
-            : EE_Registry::instance()->CFG->core->event_cpt_slug;
856
-
857
-        $what    = esc_html__('Template Settings', 'event_espresso');
858
-        $success = $this->_update_espresso_configuration(
859
-            $what,
860
-            EE_Registry::instance()->CFG->template_settings,
861
-            __FILE__,
862
-            __FUNCTION__,
863
-            __LINE__
864
-        );
865
-        if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
866
-            /** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
867
-            $rewrite_rules = LoaderFactory::getLoader()->getShared(
868
-                'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
869
-            );
870
-            $rewrite_rules->flush();
871
-        }
872
-        $this->_redirect_after_action($success, $what, 'updated', ['action' => 'template_settings']);
873
-    }
874
-
875
-
876
-    /**
877
-     * _premium_event_editor_meta_boxes
878
-     * add all metaboxes related to the event_editor
879
-     *
880
-     * @access protected
881
-     * @return void
882
-     * @throws EE_Error
883
-     * @throws ReflectionException
884
-     */
885
-    protected function _premium_event_editor_meta_boxes()
886
-    {
887
-        $this->verify_cpt_object();
888
-        add_meta_box(
889
-            'espresso_event_editor_event_options',
890
-            esc_html__('Event Registration Options', 'event_espresso'),
891
-            [$this, 'registration_options_meta_box'],
892
-            $this->page_slug,
893
-            'side',
894
-            'core'
895
-        );
896
-    }
897
-
898
-
899
-    /**
900
-     * override caf metabox
901
-     *
902
-     * @return void
903
-     * @throws EE_Error
904
-     * @throws ReflectionException
905
-     */
906
-    public function registration_options_meta_box()
907
-    {
908
-        $yes_no_values = [
909
-            ['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
910
-            ['id' => false, 'text' => esc_html__('No', 'event_espresso')],
911
-        ];
912
-
913
-        $default_reg_status_values = EEM_Registration::reg_status_array(
914
-            [
915
-                EEM_Registration::status_id_cancelled,
916
-                EEM_Registration::status_id_declined,
917
-                EEM_Registration::status_id_incomplete,
918
-                EEM_Registration::status_id_wait_list,
919
-            ],
920
-            true
921
-        );
922
-
923
-        $template_args['active_status']    = $this->_cpt_model_obj->pretty_active_status(false);
924
-        $template_args['_event']           = $this->_cpt_model_obj;
925
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
926
-
927
-        $template_args['default_registration_status']     = EEH_Form_Fields::select_input(
928
-            'default_reg_status',
929
-            $default_reg_status_values,
930
-            $this->_cpt_model_obj->default_registration_status()
931
-        );
932
-        $template_args['display_description']             = EEH_Form_Fields::select_input(
933
-            'display_desc',
934
-            $yes_no_values,
935
-            $this->_cpt_model_obj->display_description()
936
-        );
937
-        $template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
938
-            'display_ticket_selector',
939
-            $yes_no_values,
940
-            $this->_cpt_model_obj->display_ticket_selector(),
941
-            '',
942
-            '',
943
-            false
944
-        );
945
-        $template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
946
-            'EVT_default_registration_status',
947
-            $default_reg_status_values,
948
-            $this->_cpt_model_obj->default_registration_status()
949
-        );
950
-        $template_args['additional_registration_options'] = apply_filters(
951
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
952
-            '',
953
-            $template_args,
954
-            $yes_no_values,
955
-            $default_reg_status_values
956
-        );
957
-        EEH_Template::display_template(
958
-            EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
959
-            $template_args
960
-        );
961
-    }
962
-
963
-
964
-
965
-    /**
966
-     * wp_list_table_mods for caf
967
-     * ============================
968
-     */
969
-    /**
970
-     * hook into list table filters and provide filters for caffeinated list table
971
-     *
972
-     * @param array $old_filters    any existing filters present
973
-     * @param array $list_table_obj the list table object
974
-     * @return array                  new filters
975
-     * @throws EE_Error
976
-     * @throws ReflectionException
977
-     */
978
-    public function list_table_filters($old_filters, $list_table_obj)
979
-    {
980
-        $filters = [];
981
-        // first month/year filters
982
-        $filters[] = $this->espresso_event_months_dropdown();
983
-        $status    = $this->request->getRequestParam('status');
984
-        // active status dropdown
985
-        if ($status !== 'draft') {
986
-            $filters[] = $this->active_status_dropdown($this->request->getRequestParam('active_status'));
987
-            $filters[] = $this->venuesDropdown($this->request->getRequestParam('venue'));
988
-        }
989
-        // category filter
990
-        $filters[] = $this->category_dropdown();
991
-        return array_merge($old_filters, $filters);
992
-    }
993
-
994
-
995
-    /**
996
-     * espresso_event_months_dropdown
997
-     *
998
-     * @access public
999
-     * @return string                dropdown listing month/year selections for events.
1000
-     * @throws EE_Error
1001
-     */
1002
-    public function espresso_event_months_dropdown()
1003
-    {
1004
-        // what we need to do is get all PRIMARY datetimes for all events to filter on.
1005
-        // Note we need to include any other filters that are set!
1006
-        return EEH_Form_Fields::generate_event_months_dropdown(
1007
-            $this->request->getRequestParam('month_range'),
1008
-            $this->request->getRequestParam('status'),
1009
-            $this->request->getRequestParam('EVT_CAT', 0, 'int'),
1010
-            $this->request->getRequestParam('active_status')
1011
-        );
1012
-    }
1013
-
1014
-
1015
-    /**
1016
-     * returns a list of "active" statuses on the event
1017
-     *
1018
-     * @param string $current_value whatever the current active status is
1019
-     * @return string
1020
-     */
1021
-    public function active_status_dropdown($current_value = '')
1022
-    {
1023
-        $select_name = 'active_status';
1024
-        $values      = [
1025
-            'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1026
-            'active'   => esc_html__('Active', 'event_espresso'),
1027
-            'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1028
-            'expired'  => esc_html__('Expired', 'event_espresso'),
1029
-            'inactive' => esc_html__('Inactive', 'event_espresso'),
1030
-        ];
1031
-
1032
-        return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1033
-    }
1034
-
1035
-
1036
-    /**
1037
-     * returns a list of "venues"
1038
-     *
1039
-     * @param string $current_value whatever the current active status is
1040
-     * @return string
1041
-     * @throws EE_Error
1042
-     * @throws ReflectionException
1043
-     */
1044
-    protected function venuesDropdown($current_value = '')
1045
-    {
1046
-        $values = [
1047
-            '' => esc_html__('All Venues', 'event_espresso'),
1048
-        ];
1049
-        // populate the list of venues.
1050
-        $venues = EEM_Venue::instance()->get_all(['order_by' => ['VNU_name' => 'ASC']]);
1051
-
1052
-        foreach ($venues as $venue) {
1053
-            $values[ $venue->ID() ] = $venue->name();
1054
-        }
1055
-
1056
-        return EEH_Form_Fields::select_input('venue', $values, $current_value, '', 'wide');
1057
-    }
1058
-
1059
-
1060
-    /**
1061
-     * output a dropdown of the categories for the category filter on the event admin list table
1062
-     *
1063
-     * @access  public
1064
-     * @return string html
1065
-     * @throws EE_Error
1066
-     * @throws ReflectionException
1067
-     */
1068
-    public function category_dropdown()
1069
-    {
1070
-        return EEH_Form_Fields::generate_event_category_dropdown(
1071
-            $this->request->getRequestParam('EVT_CAT', -1, 'int')
1072
-        );
1073
-    }
1074
-
1075
-
1076
-    /**
1077
-     * get total number of events today
1078
-     *
1079
-     * @access public
1080
-     * @return int
1081
-     * @throws EE_Error
1082
-     */
1083
-    public function total_events_today()
1084
-    {
1085
-        $start = EEM_Datetime::instance()->convert_datetime_for_query(
1086
-            'DTT_EVT_start',
1087
-            date('Y-m-d') . ' 00:00:00',
1088
-            'Y-m-d H:i:s',
1089
-            'UTC'
1090
-        );
1091
-        $end   = EEM_Datetime::instance()->convert_datetime_for_query(
1092
-            'DTT_EVT_start',
1093
-            date('Y-m-d') . ' 23:59:59',
1094
-            'Y-m-d H:i:s',
1095
-            'UTC'
1096
-        );
1097
-        $where = [
1098
-            'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1099
-        ];
1100
-        return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1101
-    }
1102
-
1103
-
1104
-    /**
1105
-     * get total number of events this month
1106
-     *
1107
-     * @access public
1108
-     * @return int
1109
-     * @throws EE_Error
1110
-     */
1111
-    public function total_events_this_month()
1112
-    {
1113
-        // Dates
1114
-        $this_year_r     = date('Y');
1115
-        $this_month_r    = date('m');
1116
-        $days_this_month = date('t');
1117
-        $start           = EEM_Datetime::instance()->convert_datetime_for_query(
1118
-            'DTT_EVT_start',
1119
-            $this_year_r . '-' . $this_month_r . '-01 00:00:00',
1120
-            'Y-m-d H:i:s',
1121
-            'UTC'
1122
-        );
1123
-        $end             = EEM_Datetime::instance()->convert_datetime_for_query(
1124
-            'DTT_EVT_start',
1125
-            $this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1126
-            'Y-m-d H:i:s',
1127
-            'UTC'
1128
-        );
1129
-        $where           = [
1130
-            'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1131
-        ];
1132
-        return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1133
-    }
1134
-
1135
-
1136
-    /** DEFAULT TICKETS STUFF **/
1137
-
1138
-    /**
1139
-     * Output default tickets list table view.
1140
-     *
1141
-     * @throws EE_Error
1142
-     */
1143
-    public function _tickets_overview_list_table()
1144
-    {
1145
-        $this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1146
-        $this->display_admin_list_table_page_with_no_sidebar();
1147
-    }
1148
-
1149
-
1150
-    /**
1151
-     * @param int  $per_page
1152
-     * @param bool $count
1153
-     * @param bool $trashed
1154
-     * @return EE_Soft_Delete_Base_Class[]|int
1155
-     * @throws EE_Error
1156
-     */
1157
-    public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1158
-    {
1159
-        $orderby = $this->request->getRequestParam('orderby', 'TKT_name');
1160
-        $order   = $this->request->getRequestParam('order', 'ASC');
1161
-        switch ($orderby) {
1162
-            case 'TKT_name':
1163
-                $orderby = ['TKT_name' => $order];
1164
-                break;
1165
-            case 'TKT_price':
1166
-                $orderby = ['TKT_price' => $order];
1167
-                break;
1168
-            case 'TKT_uses':
1169
-                $orderby = ['TKT_uses' => $order];
1170
-                break;
1171
-            case 'TKT_min':
1172
-                $orderby = ['TKT_min' => $order];
1173
-                break;
1174
-            case 'TKT_max':
1175
-                $orderby = ['TKT_max' => $order];
1176
-                break;
1177
-            case 'TKT_qty':
1178
-                $orderby = ['TKT_qty' => $order];
1179
-                break;
1180
-        }
1181
-
1182
-        $current_page = $this->request->getRequestParam('paged', 1, 'int');
1183
-        $per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1184
-        $offset       = ($current_page - 1) * $per_page;
1185
-
1186
-        $where = [
1187
-            'TKT_is_default' => 1,
1188
-            'TKT_deleted'    => $trashed,
1189
-        ];
1190
-
1191
-        $search_term = $this->request->getRequestParam('s');
1192
-        if ($search_term) {
1193
-            $search_term = '%' . $search_term . '%';
1194
-            $where['OR'] = [
1195
-                'TKT_name'        => ['LIKE', $search_term],
1196
-                'TKT_description' => ['LIKE', $search_term],
1197
-            ];
1198
-        }
1199
-
1200
-        return $count
1201
-            ? EEM_Ticket::instance()->count_deleted_and_undeleted([$where])
1202
-            : EEM_Ticket::instance()->get_all_deleted_and_undeleted(
1203
-                [
1204
-                    $where,
1205
-                    'order_by' => $orderby,
1206
-                    'limit'    => [$offset, $per_page],
1207
-                    'group_by' => 'TKT_ID',
1208
-                ]
1209
-            );
1210
-    }
1211
-
1212
-
1213
-    /**
1214
-     * @param bool $trash
1215
-     * @throws EE_Error
1216
-     */
1217
-    protected function _trash_or_restore_ticket($trash = false)
1218
-    {
1219
-        $success = 1;
1220
-        $TKT     = EEM_Ticket::instance();
1221
-        // checkboxes?
1222
-        $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1223
-        if (! empty($checkboxes)) {
1224
-            // if array has more than one element then success message should be plural
1225
-            $success = count($checkboxes) > 1 ? 2 : 1;
1226
-            // cycle thru the boxes
1227
-            while (list($TKT_ID, $value) = each($checkboxes)) {
1228
-                if ($trash) {
1229
-                    if (! $TKT->delete_by_ID($TKT_ID)) {
1230
-                        $success = 0;
1231
-                    }
1232
-                } else {
1233
-                    if (! $TKT->restore_by_ID($TKT_ID)) {
1234
-                        $success = 0;
1235
-                    }
1236
-                }
1237
-            }
1238
-        } else {
1239
-            // grab single id and trash
1240
-            $TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1241
-            if ($trash) {
1242
-                if (! $TKT->delete_by_ID($TKT_ID)) {
1243
-                    $success = 0;
1244
-                }
1245
-            } else {
1246
-                if (! $TKT->restore_by_ID($TKT_ID)) {
1247
-                    $success = 0;
1248
-                }
1249
-            }
1250
-        }
1251
-        $action_desc = $trash ? 'moved to the trash' : 'restored';
1252
-        $query_args  = [
1253
-            'action' => 'ticket_list_table',
1254
-            'status' => $trash ? '' : 'trashed',
1255
-        ];
1256
-        $this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1257
-    }
1258
-
1259
-
1260
-    /**
1261
-     * Handles trashing default ticket.
1262
-     *
1263
-     * @throws EE_Error
1264
-     * @throws ReflectionException
1265
-     */
1266
-    protected function _delete_ticket()
1267
-    {
1268
-        $success = 1;
1269
-        // checkboxes?
1270
-        $checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1271
-        if (! empty($checkboxes)) {
1272
-            // if array has more than one element then success message should be plural
1273
-            $success = count($checkboxes) > 1 ? 2 : 1;
1274
-            // cycle thru the boxes
1275
-            while (list($TKT_ID, $value) = each($checkboxes)) {
1276
-                // delete
1277
-                if (! $this->_delete_the_ticket($TKT_ID)) {
1278
-                    $success = 0;
1279
-                }
1280
-            }
1281
-        } else {
1282
-            // grab single id and trash
1283
-            $TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1284
-            if (! $this->_delete_the_ticket($TKT_ID)) {
1285
-                $success = 0;
1286
-            }
1287
-        }
1288
-        $action_desc = 'deleted';
1289
-        $query_args  = [
1290
-            'action' => 'ticket_list_table',
1291
-            'status' => 'trashed',
1292
-        ];
1293
-        // fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1294
-        if (
1295
-            EEM_Ticket::instance()->count_deleted_and_undeleted(
1296
-                [['TKT_is_default' => 1]],
1297
-                'TKT_ID',
1298
-                true
1299
-            )
1300
-        ) {
1301
-            $query_args = [];
1302
-        }
1303
-        $this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1304
-    }
1305
-
1306
-
1307
-    /**
1308
-     * @param int $TKT_ID
1309
-     * @return bool|int
1310
-     * @throws EE_Error
1311
-     * @throws ReflectionException
1312
-     */
1313
-    protected function _delete_the_ticket($TKT_ID)
1314
-    {
1315
-        $ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1316
-        $ticket->_remove_relations('Datetime');
1317
-        // delete all related prices first
1318
-        $ticket->delete_related_permanently('Price');
1319
-        return $ticket->delete_permanently();
1320
-    }
17
+	/**
18
+	 * Extend_Events_Admin_Page constructor.
19
+	 *
20
+	 * @param bool $routing
21
+	 * @throws EE_Error
22
+	 * @throws ReflectionException
23
+	 */
24
+	public function __construct($routing = true)
25
+	{
26
+		parent::__construct($routing);
27
+		if (! defined('EVENTS_CAF_TEMPLATE_PATH')) {
28
+			define('EVENTS_CAF_TEMPLATE_PATH', EE_CORE_CAF_ADMIN_EXTEND . 'events/templates/');
29
+			define('EVENTS_CAF_ASSETS', EE_CORE_CAF_ADMIN_EXTEND . 'events/assets/');
30
+			define('EVENTS_CAF_ASSETS_URL', EE_CORE_CAF_ADMIN_EXTEND_URL . 'events/assets/');
31
+		}
32
+	}
33
+
34
+
35
+	/**
36
+	 * Sets routes.
37
+	 *
38
+	 * @throws EE_Error
39
+	 */
40
+	protected function _extend_page_config()
41
+	{
42
+		$this->_admin_base_path = EE_CORE_CAF_ADMIN_EXTEND . 'events';
43
+		// is there a evt_id in the request?
44
+		$EVT_ID             = $this->request->getRequestParam('EVT_ID', 0, 'int');
45
+		$EVT_ID             = $this->request->getRequestParam('post', $EVT_ID, 'int');
46
+		$TKT_ID             = $this->request->getRequestParam('TKT_ID', 0, 'int');
47
+		$new_page_routes    = [
48
+			'duplicate_event'          => [
49
+				'func'       => '_duplicate_event',
50
+				'capability' => 'ee_edit_event',
51
+				'obj_id'     => $EVT_ID,
52
+				'noheader'   => true,
53
+			],
54
+			'ticket_list_table'        => [
55
+				'func'       => '_tickets_overview_list_table',
56
+				'capability' => 'ee_read_default_tickets',
57
+			],
58
+			'trash_ticket'             => [
59
+				'func'       => '_trash_or_restore_ticket',
60
+				'capability' => 'ee_delete_default_ticket',
61
+				'obj_id'     => $TKT_ID,
62
+				'noheader'   => true,
63
+				'args'       => ['trash' => true],
64
+			],
65
+			'trash_tickets'            => [
66
+				'func'       => '_trash_or_restore_ticket',
67
+				'capability' => 'ee_delete_default_tickets',
68
+				'noheader'   => true,
69
+				'args'       => ['trash' => true],
70
+			],
71
+			'restore_ticket'           => [
72
+				'func'       => '_trash_or_restore_ticket',
73
+				'capability' => 'ee_delete_default_ticket',
74
+				'obj_id'     => $TKT_ID,
75
+				'noheader'   => true,
76
+			],
77
+			'restore_tickets'          => [
78
+				'func'       => '_trash_or_restore_ticket',
79
+				'capability' => 'ee_delete_default_tickets',
80
+				'noheader'   => true,
81
+			],
82
+			'delete_ticket'            => [
83
+				'func'       => '_delete_ticket',
84
+				'capability' => 'ee_delete_default_ticket',
85
+				'obj_id'     => $TKT_ID,
86
+				'noheader'   => true,
87
+			],
88
+			'delete_tickets'           => [
89
+				'func'       => '_delete_ticket',
90
+				'capability' => 'ee_delete_default_tickets',
91
+				'noheader'   => true,
92
+			],
93
+			'import_page'              => [
94
+				'func'       => '_import_page',
95
+				'capability' => 'import',
96
+			],
97
+			'import'                   => [
98
+				'func'       => '_import_events',
99
+				'capability' => 'import',
100
+				'noheader'   => true,
101
+			],
102
+			'import_events'            => [
103
+				'func'       => '_import_events',
104
+				'capability' => 'import',
105
+				'noheader'   => true,
106
+			],
107
+			'export_events'            => [
108
+				'func'       => '_events_export',
109
+				'capability' => 'export',
110
+				'noheader'   => true,
111
+			],
112
+			'export_categories'        => [
113
+				'func'       => '_categories_export',
114
+				'capability' => 'export',
115
+				'noheader'   => true,
116
+			],
117
+			'sample_export_file'       => [
118
+				'func'       => '_sample_export_file',
119
+				'capability' => 'export',
120
+				'noheader'   => true,
121
+			],
122
+			'update_template_settings' => [
123
+				'func'       => '_update_template_settings',
124
+				'capability' => 'manage_options',
125
+				'noheader'   => true,
126
+			],
127
+		];
128
+		$this->_page_routes = array_merge($this->_page_routes, $new_page_routes);
129
+		// partial route/config override
130
+		$this->_page_config['import_events']['metaboxes'] = $this->_default_espresso_metaboxes;
131
+		$this->_page_config['create_new']['metaboxes'][]  = '_premium_event_editor_meta_boxes';
132
+		$this->_page_config['create_new']['qtips'][]      = 'EE_Event_Editor_Tips';
133
+		$this->_page_config['edit']['qtips'][]            = 'EE_Event_Editor_Tips';
134
+		$this->_page_config['edit']['metaboxes'][]        = '_premium_event_editor_meta_boxes';
135
+		$this->_page_config['default']['list_table']      = 'Extend_Events_Admin_List_Table';
136
+		// add tickets tab but only if there are more than one default ticket!
137
+		$ticket_count = EEM_Ticket::instance()->count_deleted_and_undeleted(
138
+			[['TKT_is_default' => 1]],
139
+			'TKT_ID',
140
+			true
141
+		);
142
+		if ($ticket_count > 1) {
143
+			$new_page_config = [
144
+				'ticket_list_table' => [
145
+					'nav'           => [
146
+						'label' => esc_html__('Default Tickets', 'event_espresso'),
147
+						'order' => 60,
148
+					],
149
+					'list_table'    => 'Tickets_List_Table',
150
+					'require_nonce' => false,
151
+				],
152
+			];
153
+		}
154
+		// template settings
155
+		$new_page_config['template_settings'] = [
156
+			'nav'           => [
157
+				'label' => esc_html__('Templates', 'event_espresso'),
158
+				'order' => 30,
159
+			],
160
+			'metaboxes'     => array_merge($this->_default_espresso_metaboxes, ['_publish_post_box']),
161
+			'help_tabs'     => [
162
+				'general_settings_templates_help_tab' => [
163
+					'title'    => esc_html__('Templates', 'event_espresso'),
164
+					'filename' => 'general_settings_templates',
165
+				],
166
+			],
167
+			// disabled temporarily. see: https://github.com/eventespresso/eventsmart.com-website/issues/836
168
+			// 'help_tour'     => array('Templates_Help_Tour'),
169
+			'require_nonce' => false,
170
+		];
171
+		$this->_page_config                   = array_merge($this->_page_config, $new_page_config);
172
+		// add filters and actions
173
+		// modifying _views
174
+		add_filter(
175
+			'FHEE_event_datetime_metabox_add_additional_date_time_template',
176
+			[$this, 'add_additional_datetime_button'],
177
+			10,
178
+			2
179
+		);
180
+		add_filter(
181
+			'FHEE_event_datetime_metabox_clone_button_template',
182
+			[$this, 'add_datetime_clone_button'],
183
+			10,
184
+			2
185
+		);
186
+		add_filter(
187
+			'FHEE_event_datetime_metabox_timezones_template',
188
+			[$this, 'datetime_timezones_template'],
189
+			10,
190
+			2
191
+		);
192
+		// filters for event list table
193
+		add_filter('FHEE__Extend_Events_Admin_List_Table__filters', [$this, 'list_table_filters'], 10, 2);
194
+		add_filter(
195
+			'FHEE__Events_Admin_List_Table__column_actions__action_links',
196
+			[$this, 'extra_list_table_actions'],
197
+			10,
198
+			2
199
+		);
200
+		// legend item
201
+		add_filter('FHEE__Events_Admin_Page___event_legend_items__items', [$this, 'additional_legend_items']);
202
+		add_action('admin_init', [$this, 'admin_init']);
203
+	}
204
+
205
+
206
+	/**
207
+	 * admin_init
208
+	 */
209
+	public function admin_init()
210
+	{
211
+		EE_Registry::$i18n_js_strings = array_merge(
212
+			EE_Registry::$i18n_js_strings,
213
+			[
214
+				'image_confirm'          => esc_html__(
215
+					'Do you really want to delete this image? Please remember to update your event to complete the removal.',
216
+					'event_espresso'
217
+				),
218
+				'event_starts_on'        => esc_html__('Event Starts on', 'event_espresso'),
219
+				'event_ends_on'          => esc_html__('Event Ends on', 'event_espresso'),
220
+				'event_datetime_actions' => esc_html__('Actions', 'event_espresso'),
221
+				'event_clone_dt_msg'     => esc_html__('Clone this Event Date and Time', 'event_espresso'),
222
+				'remove_event_dt_msg'    => esc_html__('Remove this Event Time', 'event_espresso'),
223
+			]
224
+		);
225
+	}
226
+
227
+
228
+	/**
229
+	 * Add per page screen options to the default ticket list table view.
230
+	 */
231
+	protected function _add_screen_options_ticket_list_table()
232
+	{
233
+		$this->_per_page_screen_option();
234
+	}
235
+
236
+
237
+	/**
238
+	 * @param string $return
239
+	 * @param int    $id
240
+	 * @param string $new_title
241
+	 * @param string $new_slug
242
+	 * @return string
243
+	 */
244
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
245
+	{
246
+		$return = parent::extra_permalink_field_buttons($return, $id, $new_title, $new_slug);
247
+		// make sure this is only when editing
248
+		if (! empty($id)) {
249
+			$href   = EE_Admin_Page::add_query_args_and_nonce(
250
+				['action' => 'duplicate_event', 'EVT_ID' => $id],
251
+				$this->_admin_base_url
252
+			);
253
+			$title  = esc_attr__('Duplicate Event', 'event_espresso');
254
+			$return .= '<a href="'
255
+					   . $href
256
+					   . '" title="'
257
+					   . $title
258
+					   . '" id="ee-duplicate-event-button" class="button button-small"  value="duplicate_event">'
259
+					   . $title
260
+					   . '</a>';
261
+		}
262
+		return $return;
263
+	}
264
+
265
+
266
+	/**
267
+	 * Set the list table views for the default ticket list table view.
268
+	 */
269
+	public function _set_list_table_views_ticket_list_table()
270
+	{
271
+		$this->_views = [
272
+			'all'     => [
273
+				'slug'        => 'all',
274
+				'label'       => esc_html__('All', 'event_espresso'),
275
+				'count'       => 0,
276
+				'bulk_action' => [
277
+					'trash_tickets' => esc_html__('Move to Trash', 'event_espresso'),
278
+				],
279
+			],
280
+			'trashed' => [
281
+				'slug'        => 'trashed',
282
+				'label'       => esc_html__('Trash', 'event_espresso'),
283
+				'count'       => 0,
284
+				'bulk_action' => [
285
+					'restore_tickets' => esc_html__('Restore from Trash', 'event_espresso'),
286
+					'delete_tickets'  => esc_html__('Delete Permanently', 'event_espresso'),
287
+				],
288
+			],
289
+		];
290
+	}
291
+
292
+
293
+	/**
294
+	 * Enqueue scripts and styles for the event editor.
295
+	 */
296
+	public function load_scripts_styles_edit()
297
+	{
298
+		wp_register_script(
299
+			'ee-event-editor-heartbeat',
300
+			EVENTS_CAF_ASSETS_URL . 'event-editor-heartbeat.js',
301
+			['ee_admin_js', 'heartbeat'],
302
+			EVENT_ESPRESSO_VERSION,
303
+			true
304
+		);
305
+		wp_enqueue_script('ee-accounting');
306
+		// styles
307
+		wp_enqueue_style('espresso-ui-theme');
308
+		wp_enqueue_script('event_editor_js');
309
+		wp_enqueue_script('ee-event-editor-heartbeat');
310
+	}
311
+
312
+
313
+	/**
314
+	 * Returns template for the additional datetime.
315
+	 *
316
+	 * @param string $template
317
+	 * @param array  $template_args
318
+	 * @return string
319
+	 * @throws DomainException
320
+	 */
321
+	public function add_additional_datetime_button($template, $template_args)
322
+	{
323
+		return EEH_Template::display_template(
324
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_add_additional_time.template.php',
325
+			$template_args,
326
+			true
327
+		);
328
+	}
329
+
330
+
331
+	/**
332
+	 * Returns the template for cloning a datetime.
333
+	 *
334
+	 * @param $template
335
+	 * @param $template_args
336
+	 * @return string
337
+	 * @throws DomainException
338
+	 */
339
+	public function add_datetime_clone_button($template, $template_args)
340
+	{
341
+		return EEH_Template::display_template(
342
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_metabox_clone_button.template.php',
343
+			$template_args,
344
+			true
345
+		);
346
+	}
347
+
348
+
349
+	/**
350
+	 * Returns the template for datetime timezones.
351
+	 *
352
+	 * @param $template
353
+	 * @param $template_args
354
+	 * @return string
355
+	 * @throws DomainException
356
+	 */
357
+	public function datetime_timezones_template($template, $template_args)
358
+	{
359
+		return EEH_Template::display_template(
360
+			EVENTS_CAF_TEMPLATE_PATH . 'event_datetime_timezones.template.php',
361
+			$template_args,
362
+			true
363
+		);
364
+	}
365
+
366
+
367
+	/**
368
+	 * Sets the views for the default list table view.
369
+	 *
370
+	 * @throws EE_Error
371
+	 */
372
+	protected function _set_list_table_views_default()
373
+	{
374
+		parent::_set_list_table_views_default();
375
+		$new_views    = [
376
+			'today' => [
377
+				'slug'        => 'today',
378
+				'label'       => esc_html__('Today', 'event_espresso'),
379
+				'count'       => $this->total_events_today(),
380
+				'bulk_action' => [
381
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
382
+				],
383
+			],
384
+			'month' => [
385
+				'slug'        => 'month',
386
+				'label'       => esc_html__('This Month', 'event_espresso'),
387
+				'count'       => $this->total_events_this_month(),
388
+				'bulk_action' => [
389
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
390
+				],
391
+			],
392
+		];
393
+		$this->_views = array_merge($this->_views, $new_views);
394
+	}
395
+
396
+
397
+	/**
398
+	 * Returns the extra action links for the default list table view.
399
+	 *
400
+	 * @param array    $action_links
401
+	 * @param EE_Event $event
402
+	 * @return array
403
+	 * @throws EE_Error
404
+	 * @throws ReflectionException
405
+	 */
406
+	public function extra_list_table_actions(array $action_links, EE_Event $event)
407
+	{
408
+		if (
409
+			EE_Registry::instance()->CAP->current_user_can(
410
+				'ee_read_registrations',
411
+				'espresso_registrations_reports',
412
+				$event->ID()
413
+			)
414
+		) {
415
+			$reports_query_args = [
416
+				'action' => 'reports',
417
+				'EVT_ID' => $event->ID(),
418
+			];
419
+			$reports_link       = EE_Admin_Page::add_query_args_and_nonce($reports_query_args, REG_ADMIN_URL);
420
+			$action_links[]     = '<a href="'
421
+								  . $reports_link
422
+								  . '" title="'
423
+								  . esc_attr__('View Report', 'event_espresso')
424
+								  . '"><div class="dashicons dashicons-chart-bar"></div></a>'
425
+								  . "\n\t";
426
+		}
427
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
428
+			EE_Registry::instance()->load_helper('MSG_Template');
429
+			$action_links[] = EEH_MSG_Template::get_message_action_link(
430
+				'see_notifications_for',
431
+				null,
432
+				['EVT_ID' => $event->ID()]
433
+			);
434
+		}
435
+		return $action_links;
436
+	}
437
+
438
+
439
+	/**
440
+	 * @param $items
441
+	 * @return mixed
442
+	 */
443
+	public function additional_legend_items($items)
444
+	{
445
+		if (
446
+			EE_Registry::instance()->CAP->current_user_can(
447
+				'ee_read_registrations',
448
+				'espresso_registrations_reports'
449
+			)
450
+		) {
451
+			$items['reports'] = [
452
+				'class' => 'dashicons dashicons-chart-bar',
453
+				'desc'  => esc_html__('Event Reports', 'event_espresso'),
454
+			];
455
+		}
456
+		if (EE_Registry::instance()->CAP->current_user_can('ee_read_global_messages', 'view_filtered_messages')) {
457
+			$related_for_icon = EEH_MSG_Template::get_message_action_icon('see_notifications_for');
458
+			if (isset($related_for_icon['css_class']) && isset($related_for_icon['label'])) {
459
+				$items['view_related_messages'] = [
460
+					'class' => $related_for_icon['css_class'],
461
+					'desc'  => $related_for_icon['label'],
462
+				];
463
+			}
464
+		}
465
+		return $items;
466
+	}
467
+
468
+
469
+	/**
470
+	 * This is the callback method for the duplicate event route
471
+	 * Method looks for 'EVT_ID' in the request and retrieves that event and its details and duplicates them
472
+	 * into a new event.  We add a hook so that any plugins that add extra event details can hook into this
473
+	 * action.  Note that the dupe will have **DUPLICATE** as its title and slug.
474
+	 * After duplication the redirect is to the new event edit page.
475
+	 *
476
+	 * @return void
477
+	 * @throws EE_Error If EE_Event is not available with given ID
478
+	 * @throws ReflectionException
479
+	 * @access protected
480
+	 */
481
+	protected function _duplicate_event()
482
+	{
483
+		// first make sure the ID for the event is in the request.
484
+		//  If it isn't then we need to bail and redirect back to overview list table (cause how did we get here?)
485
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
486
+		if (! $EVT_ID) {
487
+			EE_Error::add_error(
488
+				esc_html__(
489
+					'In order to duplicate an event an Event ID is required.  None was given.',
490
+					'event_espresso'
491
+				),
492
+				__FILE__,
493
+				__FUNCTION__,
494
+				__LINE__
495
+			);
496
+			$this->_redirect_after_action(false, '', '', [], true);
497
+			return;
498
+		}
499
+		// k we've got EVT_ID so let's use that to get the event we'll duplicate
500
+		$orig_event = EEM_Event::instance()->get_one_by_ID($EVT_ID);
501
+		if (! $orig_event instanceof EE_Event) {
502
+			throw new EE_Error(
503
+				sprintf(
504
+					esc_html__('An EE_Event object could not be retrieved for the given ID (%s)', 'event_espresso'),
505
+					$EVT_ID
506
+				)
507
+			);
508
+		}
509
+		// k now let's clone the $orig_event before getting relations
510
+		$new_event = clone $orig_event;
511
+		// original datetimes
512
+		$orig_datetimes = $orig_event->get_many_related('Datetime');
513
+		// other original relations
514
+		$orig_ven = $orig_event->get_many_related('Venue');
515
+		// reset the ID and modify other details to make it clear this is a dupe
516
+		$new_event->set('EVT_ID', 0);
517
+		$new_name = $new_event->name() . ' ' . esc_html__('**DUPLICATE**', 'event_espresso');
518
+		$new_event->set('EVT_name', $new_name);
519
+		$new_event->set(
520
+			'EVT_slug',
521
+			wp_unique_post_slug(
522
+				sanitize_title($orig_event->name()),
523
+				0,
524
+				'publish',
525
+				'espresso_events',
526
+				0
527
+			)
528
+		);
529
+		$new_event->set('status', 'draft');
530
+		// duplicate discussion settings
531
+		$new_event->set('comment_status', $orig_event->get('comment_status'));
532
+		$new_event->set('ping_status', $orig_event->get('ping_status'));
533
+		// save the new event
534
+		$new_event->save();
535
+		// venues
536
+		foreach ($orig_ven as $ven) {
537
+			$new_event->_add_relation_to($ven, 'Venue');
538
+		}
539
+		$new_event->save();
540
+		// now we need to get the question group relations and handle that
541
+		// first primary question groups
542
+		$orig_primary_qgs = $orig_event->get_many_related(
543
+			'Question_Group',
544
+			[['Event_Question_Group.EQG_primary' => true]]
545
+		);
546
+		if (! empty($orig_primary_qgs)) {
547
+			foreach ($orig_primary_qgs as $obj) {
548
+				if ($obj instanceof EE_Question_Group) {
549
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_primary' => true]);
550
+				}
551
+			}
552
+		}
553
+		// next additional attendee question groups
554
+		$orig_additional_qgs = $orig_event->get_many_related(
555
+			'Question_Group',
556
+			[['Event_Question_Group.EQG_additional' => true]]
557
+		);
558
+		if (! empty($orig_additional_qgs)) {
559
+			foreach ($orig_additional_qgs as $obj) {
560
+				if ($obj instanceof EE_Question_Group) {
561
+					$new_event->_add_relation_to($obj, 'Question_Group', ['EQG_additional' => true]);
562
+				}
563
+			}
564
+		}
565
+
566
+		$new_event->save();
567
+
568
+		// k now that we have the new event saved we can loop through the datetimes and start adding relations.
569
+		$cloned_tickets = [];
570
+		foreach ($orig_datetimes as $orig_dtt) {
571
+			if (! $orig_dtt instanceof EE_Datetime) {
572
+				continue;
573
+			}
574
+			$new_dtt      = clone $orig_dtt;
575
+			$orig_tickets = $orig_dtt->tickets();
576
+			// save new dtt then add to event
577
+			$new_dtt->set('DTT_ID', 0);
578
+			$new_dtt->set('DTT_sold', 0);
579
+			$new_dtt->set_reserved(0);
580
+			$new_dtt->save();
581
+			$new_event->_add_relation_to($new_dtt, 'Datetime');
582
+			$new_event->save();
583
+			// now let's get the ticket relations setup.
584
+			foreach ((array) $orig_tickets as $orig_ticket) {
585
+				// it's possible a datetime will have no tickets so let's verify we HAVE a ticket first.
586
+				if (! $orig_ticket instanceof EE_Ticket) {
587
+					continue;
588
+				}
589
+				// is this ticket archived?  If it is then let's skip
590
+				if ($orig_ticket->get('TKT_deleted')) {
591
+					continue;
592
+				}
593
+				// does this original ticket already exist in the clone_tickets cache?
594
+				//  If so we'll just use the new ticket from it.
595
+				if (isset($cloned_tickets[ $orig_ticket->ID() ])) {
596
+					$new_ticket = $cloned_tickets[ $orig_ticket->ID() ];
597
+				} else {
598
+					$new_ticket = clone $orig_ticket;
599
+					// get relations on the $orig_ticket that we need to setup.
600
+					$orig_prices = $orig_ticket->prices();
601
+					$new_ticket->set('TKT_ID', 0);
602
+					$new_ticket->set('TKT_sold', 0);
603
+					$new_ticket->set('TKT_reserved', 0);
604
+					$new_ticket->save(); // make sure new ticket has ID.
605
+					// price relations on new ticket need to be setup.
606
+					foreach ($orig_prices as $orig_price) {
607
+						$new_price = clone $orig_price;
608
+						$new_price->set('PRC_ID', 0);
609
+						$new_price->save();
610
+						$new_ticket->_add_relation_to($new_price, 'Price');
611
+						$new_ticket->save();
612
+					}
613
+
614
+					do_action(
615
+						'AHEE__Extend_Events_Admin_Page___duplicate_event__duplicate_ticket__after',
616
+						$orig_ticket,
617
+						$new_ticket,
618
+						$orig_prices,
619
+						$orig_event,
620
+						$orig_dtt,
621
+						$new_dtt
622
+					);
623
+				}
624
+				// k now we can add the new ticket as a relation to the new datetime
625
+				// and make sure its added to our cached $cloned_tickets array
626
+				// for use with later datetimes that have the same ticket.
627
+				$new_dtt->_add_relation_to($new_ticket, 'Ticket');
628
+				$new_dtt->save();
629
+				$cloned_tickets[ $orig_ticket->ID() ] = $new_ticket;
630
+			}
631
+		}
632
+		// clone taxonomy information
633
+		$taxonomies_to_clone_with = apply_filters(
634
+			'FHEE__Extend_Events_Admin_Page___duplicate_event__taxonomies_to_clone',
635
+			['espresso_event_categories', 'espresso_event_type', 'post_tag']
636
+		);
637
+		// get terms for original event (notice)
638
+		$orig_terms = wp_get_object_terms($orig_event->ID(), $taxonomies_to_clone_with);
639
+		// loop through terms and add them to new event.
640
+		foreach ($orig_terms as $term) {
641
+			wp_set_object_terms($new_event->ID(), $term->term_id, $term->taxonomy, true);
642
+		}
643
+
644
+		// duplicate other core WP_Post items for this event.
645
+		// post thumbnail (feature image).
646
+		$feature_image_id = get_post_thumbnail_id($orig_event->ID());
647
+		if ($feature_image_id) {
648
+			update_post_meta($new_event->ID(), '_thumbnail_id', $feature_image_id);
649
+		}
650
+
651
+		// duplicate page_template setting
652
+		$page_template = get_post_meta($orig_event->ID(), '_wp_page_template', true);
653
+		if ($page_template) {
654
+			update_post_meta($new_event->ID(), '_wp_page_template', $page_template);
655
+		}
656
+
657
+		do_action('AHEE__Extend_Events_Admin_Page___duplicate_event__after', $new_event, $orig_event);
658
+		// now let's redirect to the edit page for this duplicated event if we have a new event id.
659
+		if ($new_event->ID()) {
660
+			$redirect_args = [
661
+				'post'   => $new_event->ID(),
662
+				'action' => 'edit',
663
+			];
664
+			EE_Error::add_success(
665
+				esc_html__(
666
+					'Event successfully duplicated.  Please review the details below and make any necessary edits',
667
+					'event_espresso'
668
+				)
669
+			);
670
+		} else {
671
+			$redirect_args = [
672
+				'action' => 'default',
673
+			];
674
+			EE_Error::add_error(
675
+				esc_html__('Not able to duplicate event.  Something went wrong.', 'event_espresso'),
676
+				__FILE__,
677
+				__FUNCTION__,
678
+				__LINE__
679
+			);
680
+		}
681
+		$this->_redirect_after_action(false, '', '', $redirect_args, true);
682
+	}
683
+
684
+
685
+	/**
686
+	 * Generates output for the import page.
687
+	 *
688
+	 * @throws EE_Error
689
+	 */
690
+	protected function _import_page()
691
+	{
692
+		$title = esc_html__('Import', 'event_espresso');
693
+		$intro = esc_html__(
694
+			'If you have a previously exported Event Espresso 4 information in a Comma Separated Value (CSV) file format, you can upload the file here: ',
695
+			'event_espresso'
696
+		);
697
+
698
+		$form_url = EVENTS_ADMIN_URL;
699
+		$action   = 'import_events';
700
+		$type     = 'csv';
701
+
702
+		$this->_template_args['form'] = EE_Import::instance()->upload_form(
703
+			$title,
704
+			$intro,
705
+			$form_url,
706
+			$action,
707
+			$type
708
+		);
709
+
710
+		$this->_template_args['sample_file_link']   = EE_Admin_Page::add_query_args_and_nonce(
711
+			['action' => 'sample_export_file'],
712
+			$this->_admin_base_url
713
+		);
714
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
715
+			EVENTS_CAF_TEMPLATE_PATH . 'import_page.template.php',
716
+			$this->_template_args,
717
+			true
718
+		);
719
+		$this->display_admin_page_with_sidebar();
720
+	}
721
+
722
+
723
+	/**
724
+	 * _import_events
725
+	 * This handles displaying the screen and running imports for importing events.
726
+	 *
727
+	 * @return void
728
+	 * @throws EE_Error
729
+	 */
730
+	protected function _import_events()
731
+	{
732
+		require_once(EE_CLASSES . 'EE_Import.class.php');
733
+		$success = EE_Import::instance()->import();
734
+		$this->_redirect_after_action(
735
+			$success,
736
+			esc_html__('Import File', 'event_espresso'),
737
+			'ran',
738
+			['action' => 'import_page'],
739
+			true
740
+		);
741
+	}
742
+
743
+
744
+	/**
745
+	 * _events_export
746
+	 * Will export all (or just the given event) to a Excel compatible file.
747
+	 *
748
+	 * @access protected
749
+	 * @return void
750
+	 */
751
+	protected function _events_export()
752
+	{
753
+		$EVT_ID = $this->request->getRequestParam('EVT_ID', 0, 'int');
754
+		$EVT_ID = $this->request->getRequestParam('EVT_IDs', $EVT_ID, 'int');
755
+		$this->request->mergeRequestParams(
756
+			[
757
+				'export' => 'report',
758
+				'action' => 'all_event_data',
759
+				'EVT_ID' => $EVT_ID,
760
+			]
761
+		);
762
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
763
+			require_once(EE_CLASSES . 'EE_Export.class.php');
764
+			$EE_Export = EE_Export::instance($this->request->requestParams());
765
+			$EE_Export->export();
766
+		}
767
+	}
768
+
769
+
770
+	/**
771
+	 * handle category exports()
772
+	 *
773
+	 * @return void
774
+	 */
775
+	protected function _categories_export()
776
+	{
777
+		$EVT_ID = $this->request->getRequestParam('EVT_CAT_ID', 0, 'int');
778
+		$this->request->mergeRequestParams(
779
+			[
780
+				'export' => 'report',
781
+				'action' => 'categories',
782
+				'EVT_ID' => $EVT_ID,
783
+			]
784
+		);
785
+		if (is_readable(EE_CLASSES . 'EE_Export.class.php')) {
786
+			require_once(EE_CLASSES . 'EE_Export.class.php');
787
+			$EE_Export = EE_Export::instance($this->request->requestParams());
788
+			$EE_Export->export();
789
+		}
790
+	}
791
+
792
+
793
+	/**
794
+	 * Creates a sample CSV file for importing
795
+	 */
796
+	protected function _sample_export_file()
797
+	{
798
+		// require_once(EE_CLASSES . 'EE_Export.class.php');
799
+		EE_Export::instance()->export_sample();
800
+	}
801
+
802
+
803
+	/*************        Template Settings        *************/
804
+	/**
805
+	 * Generates template settings page output
806
+	 *
807
+	 * @throws DomainException
808
+	 * @throws EE_Error
809
+	 */
810
+	protected function _template_settings()
811
+	{
812
+		$this->_template_args['values'] = $this->_yes_no_values;
813
+		/**
814
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
815
+		 * from General_Settings_Admin_Page to here.
816
+		 */
817
+		$this->_template_args = apply_filters(
818
+			'FHEE__General_Settings_Admin_Page__template_settings__template_args',
819
+			$this->_template_args
820
+		);
821
+		$this->_set_add_edit_form_tags('update_template_settings');
822
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
823
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
824
+			EVENTS_CAF_TEMPLATE_PATH . 'template_settings.template.php',
825
+			$this->_template_args,
826
+			true
827
+		);
828
+		$this->display_admin_page_with_sidebar();
829
+	}
830
+
831
+
832
+	/**
833
+	 * Handler for updating template settings.
834
+	 *
835
+	 * @throws EE_Error
836
+	 */
837
+	protected function _update_template_settings()
838
+	{
839
+		/**
840
+		 * Note leaving this filter in for backward compatibility this was moved in 4.6.x
841
+		 * from General_Settings_Admin_Page to here.
842
+		 */
843
+		EE_Registry::instance()->CFG->template_settings = apply_filters(
844
+			'FHEE__General_Settings_Admin_Page__update_template_settings__data',
845
+			EE_Registry::instance()->CFG->template_settings,
846
+			$this->request->requestParams()
847
+		);
848
+		// update custom post type slugs and detect if we need to flush rewrite rules
849
+		$old_slug = EE_Registry::instance()->CFG->core->event_cpt_slug;
850
+
851
+		$event_cpt_slug = $this->request->getRequestParam('event_cpt_slug');
852
+
853
+		EE_Registry::instance()->CFG->core->event_cpt_slug = $event_cpt_slug
854
+			? EEH_URL::slugify($event_cpt_slug, 'events')
855
+			: EE_Registry::instance()->CFG->core->event_cpt_slug;
856
+
857
+		$what    = esc_html__('Template Settings', 'event_espresso');
858
+		$success = $this->_update_espresso_configuration(
859
+			$what,
860
+			EE_Registry::instance()->CFG->template_settings,
861
+			__FILE__,
862
+			__FUNCTION__,
863
+			__LINE__
864
+		);
865
+		if (EE_Registry::instance()->CFG->core->event_cpt_slug != $old_slug) {
866
+			/** @var EventEspresso\core\domain\services\custom_post_types\RewriteRules $rewrite_rules */
867
+			$rewrite_rules = LoaderFactory::getLoader()->getShared(
868
+				'EventEspresso\core\domain\services\custom_post_types\RewriteRules'
869
+			);
870
+			$rewrite_rules->flush();
871
+		}
872
+		$this->_redirect_after_action($success, $what, 'updated', ['action' => 'template_settings']);
873
+	}
874
+
875
+
876
+	/**
877
+	 * _premium_event_editor_meta_boxes
878
+	 * add all metaboxes related to the event_editor
879
+	 *
880
+	 * @access protected
881
+	 * @return void
882
+	 * @throws EE_Error
883
+	 * @throws ReflectionException
884
+	 */
885
+	protected function _premium_event_editor_meta_boxes()
886
+	{
887
+		$this->verify_cpt_object();
888
+		add_meta_box(
889
+			'espresso_event_editor_event_options',
890
+			esc_html__('Event Registration Options', 'event_espresso'),
891
+			[$this, 'registration_options_meta_box'],
892
+			$this->page_slug,
893
+			'side',
894
+			'core'
895
+		);
896
+	}
897
+
898
+
899
+	/**
900
+	 * override caf metabox
901
+	 *
902
+	 * @return void
903
+	 * @throws EE_Error
904
+	 * @throws ReflectionException
905
+	 */
906
+	public function registration_options_meta_box()
907
+	{
908
+		$yes_no_values = [
909
+			['id' => true, 'text' => esc_html__('Yes', 'event_espresso')],
910
+			['id' => false, 'text' => esc_html__('No', 'event_espresso')],
911
+		];
912
+
913
+		$default_reg_status_values = EEM_Registration::reg_status_array(
914
+			[
915
+				EEM_Registration::status_id_cancelled,
916
+				EEM_Registration::status_id_declined,
917
+				EEM_Registration::status_id_incomplete,
918
+				EEM_Registration::status_id_wait_list,
919
+			],
920
+			true
921
+		);
922
+
923
+		$template_args['active_status']    = $this->_cpt_model_obj->pretty_active_status(false);
924
+		$template_args['_event']           = $this->_cpt_model_obj;
925
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
926
+
927
+		$template_args['default_registration_status']     = EEH_Form_Fields::select_input(
928
+			'default_reg_status',
929
+			$default_reg_status_values,
930
+			$this->_cpt_model_obj->default_registration_status()
931
+		);
932
+		$template_args['display_description']             = EEH_Form_Fields::select_input(
933
+			'display_desc',
934
+			$yes_no_values,
935
+			$this->_cpt_model_obj->display_description()
936
+		);
937
+		$template_args['display_ticket_selector']         = EEH_Form_Fields::select_input(
938
+			'display_ticket_selector',
939
+			$yes_no_values,
940
+			$this->_cpt_model_obj->display_ticket_selector(),
941
+			'',
942
+			'',
943
+			false
944
+		);
945
+		$template_args['EVT_default_registration_status'] = EEH_Form_Fields::select_input(
946
+			'EVT_default_registration_status',
947
+			$default_reg_status_values,
948
+			$this->_cpt_model_obj->default_registration_status()
949
+		);
950
+		$template_args['additional_registration_options'] = apply_filters(
951
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
952
+			'',
953
+			$template_args,
954
+			$yes_no_values,
955
+			$default_reg_status_values
956
+		);
957
+		EEH_Template::display_template(
958
+			EVENTS_CAF_TEMPLATE_PATH . 'event_registration_options.template.php',
959
+			$template_args
960
+		);
961
+	}
962
+
963
+
964
+
965
+	/**
966
+	 * wp_list_table_mods for caf
967
+	 * ============================
968
+	 */
969
+	/**
970
+	 * hook into list table filters and provide filters for caffeinated list table
971
+	 *
972
+	 * @param array $old_filters    any existing filters present
973
+	 * @param array $list_table_obj the list table object
974
+	 * @return array                  new filters
975
+	 * @throws EE_Error
976
+	 * @throws ReflectionException
977
+	 */
978
+	public function list_table_filters($old_filters, $list_table_obj)
979
+	{
980
+		$filters = [];
981
+		// first month/year filters
982
+		$filters[] = $this->espresso_event_months_dropdown();
983
+		$status    = $this->request->getRequestParam('status');
984
+		// active status dropdown
985
+		if ($status !== 'draft') {
986
+			$filters[] = $this->active_status_dropdown($this->request->getRequestParam('active_status'));
987
+			$filters[] = $this->venuesDropdown($this->request->getRequestParam('venue'));
988
+		}
989
+		// category filter
990
+		$filters[] = $this->category_dropdown();
991
+		return array_merge($old_filters, $filters);
992
+	}
993
+
994
+
995
+	/**
996
+	 * espresso_event_months_dropdown
997
+	 *
998
+	 * @access public
999
+	 * @return string                dropdown listing month/year selections for events.
1000
+	 * @throws EE_Error
1001
+	 */
1002
+	public function espresso_event_months_dropdown()
1003
+	{
1004
+		// what we need to do is get all PRIMARY datetimes for all events to filter on.
1005
+		// Note we need to include any other filters that are set!
1006
+		return EEH_Form_Fields::generate_event_months_dropdown(
1007
+			$this->request->getRequestParam('month_range'),
1008
+			$this->request->getRequestParam('status'),
1009
+			$this->request->getRequestParam('EVT_CAT', 0, 'int'),
1010
+			$this->request->getRequestParam('active_status')
1011
+		);
1012
+	}
1013
+
1014
+
1015
+	/**
1016
+	 * returns a list of "active" statuses on the event
1017
+	 *
1018
+	 * @param string $current_value whatever the current active status is
1019
+	 * @return string
1020
+	 */
1021
+	public function active_status_dropdown($current_value = '')
1022
+	{
1023
+		$select_name = 'active_status';
1024
+		$values      = [
1025
+			'none'     => esc_html__('Show Active/Inactive', 'event_espresso'),
1026
+			'active'   => esc_html__('Active', 'event_espresso'),
1027
+			'upcoming' => esc_html__('Upcoming', 'event_espresso'),
1028
+			'expired'  => esc_html__('Expired', 'event_espresso'),
1029
+			'inactive' => esc_html__('Inactive', 'event_espresso'),
1030
+		];
1031
+
1032
+		return EEH_Form_Fields::select_input($select_name, $values, $current_value, '', 'wide');
1033
+	}
1034
+
1035
+
1036
+	/**
1037
+	 * returns a list of "venues"
1038
+	 *
1039
+	 * @param string $current_value whatever the current active status is
1040
+	 * @return string
1041
+	 * @throws EE_Error
1042
+	 * @throws ReflectionException
1043
+	 */
1044
+	protected function venuesDropdown($current_value = '')
1045
+	{
1046
+		$values = [
1047
+			'' => esc_html__('All Venues', 'event_espresso'),
1048
+		];
1049
+		// populate the list of venues.
1050
+		$venues = EEM_Venue::instance()->get_all(['order_by' => ['VNU_name' => 'ASC']]);
1051
+
1052
+		foreach ($venues as $venue) {
1053
+			$values[ $venue->ID() ] = $venue->name();
1054
+		}
1055
+
1056
+		return EEH_Form_Fields::select_input('venue', $values, $current_value, '', 'wide');
1057
+	}
1058
+
1059
+
1060
+	/**
1061
+	 * output a dropdown of the categories for the category filter on the event admin list table
1062
+	 *
1063
+	 * @access  public
1064
+	 * @return string html
1065
+	 * @throws EE_Error
1066
+	 * @throws ReflectionException
1067
+	 */
1068
+	public function category_dropdown()
1069
+	{
1070
+		return EEH_Form_Fields::generate_event_category_dropdown(
1071
+			$this->request->getRequestParam('EVT_CAT', -1, 'int')
1072
+		);
1073
+	}
1074
+
1075
+
1076
+	/**
1077
+	 * get total number of events today
1078
+	 *
1079
+	 * @access public
1080
+	 * @return int
1081
+	 * @throws EE_Error
1082
+	 */
1083
+	public function total_events_today()
1084
+	{
1085
+		$start = EEM_Datetime::instance()->convert_datetime_for_query(
1086
+			'DTT_EVT_start',
1087
+			date('Y-m-d') . ' 00:00:00',
1088
+			'Y-m-d H:i:s',
1089
+			'UTC'
1090
+		);
1091
+		$end   = EEM_Datetime::instance()->convert_datetime_for_query(
1092
+			'DTT_EVT_start',
1093
+			date('Y-m-d') . ' 23:59:59',
1094
+			'Y-m-d H:i:s',
1095
+			'UTC'
1096
+		);
1097
+		$where = [
1098
+			'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1099
+		];
1100
+		return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1101
+	}
1102
+
1103
+
1104
+	/**
1105
+	 * get total number of events this month
1106
+	 *
1107
+	 * @access public
1108
+	 * @return int
1109
+	 * @throws EE_Error
1110
+	 */
1111
+	public function total_events_this_month()
1112
+	{
1113
+		// Dates
1114
+		$this_year_r     = date('Y');
1115
+		$this_month_r    = date('m');
1116
+		$days_this_month = date('t');
1117
+		$start           = EEM_Datetime::instance()->convert_datetime_for_query(
1118
+			'DTT_EVT_start',
1119
+			$this_year_r . '-' . $this_month_r . '-01 00:00:00',
1120
+			'Y-m-d H:i:s',
1121
+			'UTC'
1122
+		);
1123
+		$end             = EEM_Datetime::instance()->convert_datetime_for_query(
1124
+			'DTT_EVT_start',
1125
+			$this_year_r . '-' . $this_month_r . '-' . $days_this_month . ' 23:59:59',
1126
+			'Y-m-d H:i:s',
1127
+			'UTC'
1128
+		);
1129
+		$where           = [
1130
+			'Datetime.DTT_EVT_start' => ['BETWEEN', [$start, $end]],
1131
+		];
1132
+		return EEM_Event::instance()->count([$where, 'caps' => 'read_admin'], 'EVT_ID', true);
1133
+	}
1134
+
1135
+
1136
+	/** DEFAULT TICKETS STUFF **/
1137
+
1138
+	/**
1139
+	 * Output default tickets list table view.
1140
+	 *
1141
+	 * @throws EE_Error
1142
+	 */
1143
+	public function _tickets_overview_list_table()
1144
+	{
1145
+		$this->_search_btn_label = esc_html__('Tickets', 'event_espresso');
1146
+		$this->display_admin_list_table_page_with_no_sidebar();
1147
+	}
1148
+
1149
+
1150
+	/**
1151
+	 * @param int  $per_page
1152
+	 * @param bool $count
1153
+	 * @param bool $trashed
1154
+	 * @return EE_Soft_Delete_Base_Class[]|int
1155
+	 * @throws EE_Error
1156
+	 */
1157
+	public function get_default_tickets($per_page = 10, $count = false, $trashed = false)
1158
+	{
1159
+		$orderby = $this->request->getRequestParam('orderby', 'TKT_name');
1160
+		$order   = $this->request->getRequestParam('order', 'ASC');
1161
+		switch ($orderby) {
1162
+			case 'TKT_name':
1163
+				$orderby = ['TKT_name' => $order];
1164
+				break;
1165
+			case 'TKT_price':
1166
+				$orderby = ['TKT_price' => $order];
1167
+				break;
1168
+			case 'TKT_uses':
1169
+				$orderby = ['TKT_uses' => $order];
1170
+				break;
1171
+			case 'TKT_min':
1172
+				$orderby = ['TKT_min' => $order];
1173
+				break;
1174
+			case 'TKT_max':
1175
+				$orderby = ['TKT_max' => $order];
1176
+				break;
1177
+			case 'TKT_qty':
1178
+				$orderby = ['TKT_qty' => $order];
1179
+				break;
1180
+		}
1181
+
1182
+		$current_page = $this->request->getRequestParam('paged', 1, 'int');
1183
+		$per_page     = $this->request->getRequestParam('perpage', $per_page, 'int');
1184
+		$offset       = ($current_page - 1) * $per_page;
1185
+
1186
+		$where = [
1187
+			'TKT_is_default' => 1,
1188
+			'TKT_deleted'    => $trashed,
1189
+		];
1190
+
1191
+		$search_term = $this->request->getRequestParam('s');
1192
+		if ($search_term) {
1193
+			$search_term = '%' . $search_term . '%';
1194
+			$where['OR'] = [
1195
+				'TKT_name'        => ['LIKE', $search_term],
1196
+				'TKT_description' => ['LIKE', $search_term],
1197
+			];
1198
+		}
1199
+
1200
+		return $count
1201
+			? EEM_Ticket::instance()->count_deleted_and_undeleted([$where])
1202
+			: EEM_Ticket::instance()->get_all_deleted_and_undeleted(
1203
+				[
1204
+					$where,
1205
+					'order_by' => $orderby,
1206
+					'limit'    => [$offset, $per_page],
1207
+					'group_by' => 'TKT_ID',
1208
+				]
1209
+			);
1210
+	}
1211
+
1212
+
1213
+	/**
1214
+	 * @param bool $trash
1215
+	 * @throws EE_Error
1216
+	 */
1217
+	protected function _trash_or_restore_ticket($trash = false)
1218
+	{
1219
+		$success = 1;
1220
+		$TKT     = EEM_Ticket::instance();
1221
+		// checkboxes?
1222
+		$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1223
+		if (! empty($checkboxes)) {
1224
+			// if array has more than one element then success message should be plural
1225
+			$success = count($checkboxes) > 1 ? 2 : 1;
1226
+			// cycle thru the boxes
1227
+			while (list($TKT_ID, $value) = each($checkboxes)) {
1228
+				if ($trash) {
1229
+					if (! $TKT->delete_by_ID($TKT_ID)) {
1230
+						$success = 0;
1231
+					}
1232
+				} else {
1233
+					if (! $TKT->restore_by_ID($TKT_ID)) {
1234
+						$success = 0;
1235
+					}
1236
+				}
1237
+			}
1238
+		} else {
1239
+			// grab single id and trash
1240
+			$TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1241
+			if ($trash) {
1242
+				if (! $TKT->delete_by_ID($TKT_ID)) {
1243
+					$success = 0;
1244
+				}
1245
+			} else {
1246
+				if (! $TKT->restore_by_ID($TKT_ID)) {
1247
+					$success = 0;
1248
+				}
1249
+			}
1250
+		}
1251
+		$action_desc = $trash ? 'moved to the trash' : 'restored';
1252
+		$query_args  = [
1253
+			'action' => 'ticket_list_table',
1254
+			'status' => $trash ? '' : 'trashed',
1255
+		];
1256
+		$this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1257
+	}
1258
+
1259
+
1260
+	/**
1261
+	 * Handles trashing default ticket.
1262
+	 *
1263
+	 * @throws EE_Error
1264
+	 * @throws ReflectionException
1265
+	 */
1266
+	protected function _delete_ticket()
1267
+	{
1268
+		$success = 1;
1269
+		// checkboxes?
1270
+		$checkboxes = $this->request->getRequestParam('checkbox', [], 'int', true);
1271
+		if (! empty($checkboxes)) {
1272
+			// if array has more than one element then success message should be plural
1273
+			$success = count($checkboxes) > 1 ? 2 : 1;
1274
+			// cycle thru the boxes
1275
+			while (list($TKT_ID, $value) = each($checkboxes)) {
1276
+				// delete
1277
+				if (! $this->_delete_the_ticket($TKT_ID)) {
1278
+					$success = 0;
1279
+				}
1280
+			}
1281
+		} else {
1282
+			// grab single id and trash
1283
+			$TKT_ID = $this->request->getRequestParam('TKT_ID', 0, 'int');
1284
+			if (! $this->_delete_the_ticket($TKT_ID)) {
1285
+				$success = 0;
1286
+			}
1287
+		}
1288
+		$action_desc = 'deleted';
1289
+		$query_args  = [
1290
+			'action' => 'ticket_list_table',
1291
+			'status' => 'trashed',
1292
+		];
1293
+		// fail safe.  If the default ticket count === 1 then we need to redirect to event overview.
1294
+		if (
1295
+			EEM_Ticket::instance()->count_deleted_and_undeleted(
1296
+				[['TKT_is_default' => 1]],
1297
+				'TKT_ID',
1298
+				true
1299
+			)
1300
+		) {
1301
+			$query_args = [];
1302
+		}
1303
+		$this->_redirect_after_action($success, esc_html__('Tickets', 'event_espresso'), $action_desc, $query_args);
1304
+	}
1305
+
1306
+
1307
+	/**
1308
+	 * @param int $TKT_ID
1309
+	 * @return bool|int
1310
+	 * @throws EE_Error
1311
+	 * @throws ReflectionException
1312
+	 */
1313
+	protected function _delete_the_ticket($TKT_ID)
1314
+	{
1315
+		$ticket = EEM_Ticket::instance()->get_one_by_ID($TKT_ID);
1316
+		$ticket->_remove_relations('Datetime');
1317
+		// delete all related prices first
1318
+		$ticket->delete_related_permanently('Price');
1319
+		return $ticket->delete_permanently();
1320
+	}
1321 1321
 }
Please login to merge, or discard this patch.