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