Completed
Branch CASC/preview-page (f4255e)
by
unknown
36:10 queued 17:15
created
admin_pages/events/Events_Admin_Page.core.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -2097,7 +2097,6 @@  discard block
 block discarded – undo
2097 2097
      * _delete_event
2098 2098
      *
2099 2099
      * @access protected
2100
-     * @param bool $redirect_after
2101 2100
      */
2102 2101
     protected function _delete_event()
2103 2102
     {
@@ -2197,6 +2196,7 @@  discard block
 block discarded – undo
2197 2196
     /**
2198 2197
      * Uses the querystring and job option to figure out what we intend to delete.
2199 2198
      * @since $VID:$
2199
+     * @param string $deletion_job_code
2200 2200
      * @return array top-level keys are model names, and their values are arrays of IDs.
2201 2201
      * @throws EE_Error
2202 2202
      * @throws InvalidArgumentException
Please login to merge, or discard this patch.
Indentation   +2796 added lines, -2796 removed lines patch added patch discarded remove patch
@@ -18,2800 +18,2800 @@
 block discarded – undo
18 18
 class Events_Admin_Page extends EE_Admin_Page_CPT
19 19
 {
20 20
 
21
-    /**
22
-     * This will hold the event object for event_details screen.
23
-     *
24
-     * @access protected
25
-     * @var EE_Event $_event
26
-     */
27
-    protected $_event;
28
-
29
-
30
-    /**
31
-     * This will hold the category object for category_details screen.
32
-     *
33
-     * @var stdClass $_category
34
-     */
35
-    protected $_category;
36
-
37
-
38
-    /**
39
-     * This will hold the event model instance
40
-     *
41
-     * @var EEM_Event $_event_model
42
-     */
43
-    protected $_event_model;
44
-
45
-
46
-    /**
47
-     * @var EE_Event
48
-     */
49
-    protected $_cpt_model_obj = false;
50
-
51
-    /**
52
-     * Used to hold onto a form across various stages of a request.
53
-     * @var EE_Form_Section_Proper
54
-     */
55
-    protected $form;
56
-
57
-    /**
58
-     * Used so we don't have to repeatedly fetch a potentially large array of data from the WP options table.
59
-     * @var array
60
-     */
61
-    protected $models_and_ids_to_delete;
62
-
63
-
64
-    /**
65
-     * Initialize page props for this admin page group.
66
-     */
67
-    protected function _init_page_props()
68
-    {
69
-        $this->page_slug = EVENTS_PG_SLUG;
70
-        $this->page_label = EVENTS_LABEL;
71
-        $this->_admin_base_url = EVENTS_ADMIN_URL;
72
-        $this->_admin_base_path = EVENTS_ADMIN;
73
-        $this->_cpt_model_names = array(
74
-            'create_new' => 'EEM_Event',
75
-            'edit'       => 'EEM_Event',
76
-        );
77
-        $this->_cpt_edit_routes = array(
78
-            'espresso_events' => 'edit',
79
-        );
80
-        add_action(
81
-            'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
82
-            array($this, 'verify_event_edit'),
83
-            10,
84
-            2
85
-        );
86
-    }
87
-
88
-
89
-    /**
90
-     * Sets the ajax hooks used for this admin page group.
91
-     */
92
-    protected function _ajax_hooks()
93
-    {
94
-        add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
95
-    }
96
-
97
-
98
-    /**
99
-     * Sets the page properties for this admin page group.
100
-     */
101
-    protected function _define_page_props()
102
-    {
103
-        $this->_admin_page_title = EVENTS_LABEL;
104
-        $this->_labels = array(
105
-            'buttons'      => array(
106
-                'add'             => esc_html__('Add New Event', 'event_espresso'),
107
-                'edit'            => esc_html__('Edit Event', 'event_espresso'),
108
-                'delete'          => esc_html__('Delete Event', 'event_espresso'),
109
-                'add_category'    => esc_html__('Add New Category', 'event_espresso'),
110
-                'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
111
-                'delete_category' => esc_html__('Delete Category', 'event_espresso'),
112
-            ),
113
-            'editor_title' => array(
114
-                'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
115
-            ),
116
-            'publishbox'   => array(
117
-                'create_new'        => esc_html__('Save New Event', 'event_espresso'),
118
-                'edit'              => esc_html__('Update Event', 'event_espresso'),
119
-                'add_category'      => esc_html__('Save New Category', 'event_espresso'),
120
-                'edit_category'     => esc_html__('Update Category', 'event_espresso'),
121
-                'template_settings' => esc_html__('Update Settings', 'event_espresso'),
122
-            ),
123
-        );
124
-    }
125
-
126
-
127
-    /**
128
-     * Sets the page routes property for this admin page group.
129
-     */
130
-    protected function _set_page_routes()
131
-    {
132
-        // load formatter helper
133
-        // load field generator helper
134
-        // is there a evt_id in the request?
135
-        $evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
136
-            ? $this->_req_data['EVT_ID']
137
-            : 0;
138
-        $evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
139
-        $this->_page_routes = array(
140
-            'default'                       => array(
141
-                'func'       => '_events_overview_list_table',
142
-                'capability' => 'ee_read_events',
143
-            ),
144
-            'create_new'                    => array(
145
-                'func'       => '_create_new_cpt_item',
146
-                'capability' => 'ee_edit_events',
147
-            ),
148
-            'edit'                          => array(
149
-                'func'       => '_edit_cpt_item',
150
-                'capability' => 'ee_edit_event',
151
-                'obj_id'     => $evt_id,
152
-            ),
153
-            'copy_event'                    => array(
154
-                'func'       => '_copy_events',
155
-                'capability' => 'ee_edit_event',
156
-                'obj_id'     => $evt_id,
157
-                'noheader'   => true,
158
-            ),
159
-            'trash_event'                   => array(
160
-                'func'       => '_trash_or_restore_event',
161
-                'args'       => array('event_status' => 'trash'),
162
-                'capability' => 'ee_delete_event',
163
-                'obj_id'     => $evt_id,
164
-                'noheader'   => true,
165
-            ),
166
-            'trash_events'                  => array(
167
-                'func'       => '_trash_or_restore_events',
168
-                'args'       => array('event_status' => 'trash'),
169
-                'capability' => 'ee_delete_events',
170
-                'noheader'   => true,
171
-            ),
172
-            'restore_event'                 => array(
173
-                'func'       => '_trash_or_restore_event',
174
-                'args'       => array('event_status' => 'draft'),
175
-                'capability' => 'ee_delete_event',
176
-                'obj_id'     => $evt_id,
177
-                'noheader'   => true,
178
-            ),
179
-            'restore_events'                => array(
180
-                'func'       => '_trash_or_restore_events',
181
-                'args'       => array('event_status' => 'draft'),
182
-                'capability' => 'ee_delete_events',
183
-                'noheader'   => true,
184
-            ),
185
-            'delete_event'                  => array(
186
-                'func'       => '_delete_event',
187
-                'capability' => 'ee_delete_event',
188
-                'obj_id'     => $evt_id,
189
-                'noheader'   => true,
190
-            ),
191
-            'delete_events'                 => array(
192
-                'func'       => '_delete_events',
193
-                'capability' => 'ee_delete_events',
194
-                'noheader'   => true,
195
-            ),
196
-            'view_report'                   => array(
197
-                'func'      => '_view_report',
198
-                'capablity' => 'ee_edit_events',
199
-            ),
200
-            'default_event_settings'        => array(
201
-                'func'       => '_default_event_settings',
202
-                'capability' => 'manage_options',
203
-            ),
204
-            'update_default_event_settings' => array(
205
-                'func'       => '_update_default_event_settings',
206
-                'capability' => 'manage_options',
207
-                'noheader'   => true,
208
-            ),
209
-            'template_settings'             => array(
210
-                'func'       => '_template_settings',
211
-                'capability' => 'manage_options',
212
-            ),
213
-            // event category tab related
214
-            'add_category'                  => array(
215
-                'func'       => '_category_details',
216
-                'capability' => 'ee_edit_event_category',
217
-                'args'       => array('add'),
218
-            ),
219
-            'edit_category'                 => array(
220
-                'func'       => '_category_details',
221
-                'capability' => 'ee_edit_event_category',
222
-                'args'       => array('edit'),
223
-            ),
224
-            'delete_categories'             => array(
225
-                'func'       => '_delete_categories',
226
-                'capability' => 'ee_delete_event_category',
227
-                'noheader'   => true,
228
-            ),
229
-            'delete_category'               => array(
230
-                'func'       => '_delete_categories',
231
-                'capability' => 'ee_delete_event_category',
232
-                'noheader'   => true,
233
-            ),
234
-            'insert_category'               => array(
235
-                'func'       => '_insert_or_update_category',
236
-                'args'       => array('new_category' => true),
237
-                'capability' => 'ee_edit_event_category',
238
-                'noheader'   => true,
239
-            ),
240
-            'update_category'               => array(
241
-                'func'       => '_insert_or_update_category',
242
-                'args'       => array('new_category' => false),
243
-                'capability' => 'ee_edit_event_category',
244
-                'noheader'   => true,
245
-            ),
246
-            'category_list'                 => array(
247
-                'func'       => '_category_list_table',
248
-                'capability' => 'ee_manage_event_categories',
249
-            ),
250
-            'preview_deletion' => [
251
-                'func' => 'previewDeletion',
252
-                'capability' => 'ee_delete_events',
253
-            ],
254
-            'confirm_deletion' => [
255
-                'func' => 'confirmDeletion',
256
-                'capability' => 'ee_delete_events',
257
-                'noheader' => true,
258
-                'headers_sent_route' => 'preview_deletion',
259
-            ]
260
-        );
261
-    }
262
-
263
-
264
-    /**
265
-     * Set the _page_config property for this admin page group.
266
-     */
267
-    protected function _set_page_config()
268
-    {
269
-        $this->_page_config = array(
270
-            'default'                => array(
271
-                'nav'           => array(
272
-                    'label' => esc_html__('Overview', 'event_espresso'),
273
-                    'order' => 10,
274
-                ),
275
-                'list_table'    => 'Events_Admin_List_Table',
276
-                'help_tabs'     => array(
277
-                    'events_overview_help_tab'                       => array(
278
-                        'title'    => esc_html__('Events Overview', 'event_espresso'),
279
-                        'filename' => 'events_overview',
280
-                    ),
281
-                    'events_overview_table_column_headings_help_tab' => array(
282
-                        'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
283
-                        'filename' => 'events_overview_table_column_headings',
284
-                    ),
285
-                    'events_overview_filters_help_tab'               => array(
286
-                        'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
287
-                        'filename' => 'events_overview_filters',
288
-                    ),
289
-                    'events_overview_view_help_tab'                  => array(
290
-                        'title'    => esc_html__('Events Overview Views', 'event_espresso'),
291
-                        'filename' => 'events_overview_views',
292
-                    ),
293
-                    'events_overview_other_help_tab'                 => array(
294
-                        'title'    => esc_html__('Events Overview Other', 'event_espresso'),
295
-                        'filename' => 'events_overview_other',
296
-                    ),
297
-                ),
298
-                'help_tour'     => array(
299
-                    'Event_Overview_Help_Tour',
300
-                    // 'New_Features_Test_Help_Tour' for testing multiple help tour
301
-                ),
302
-                'qtips'         => array(
303
-                    'EE_Event_List_Table_Tips',
304
-                ),
305
-                'require_nonce' => false,
306
-            ),
307
-            'create_new'             => array(
308
-                'nav'           => array(
309
-                    'label'      => esc_html__('Add Event', 'event_espresso'),
310
-                    'order'      => 5,
311
-                    'persistent' => false,
312
-                ),
313
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
314
-                'help_tabs'     => array(
315
-                    'event_editor_help_tab'                            => array(
316
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
317
-                        'filename' => 'event_editor',
318
-                    ),
319
-                    'event_editor_title_richtexteditor_help_tab'       => array(
320
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
321
-                        'filename' => 'event_editor_title_richtexteditor',
322
-                    ),
323
-                    'event_editor_venue_details_help_tab'              => array(
324
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
325
-                        'filename' => 'event_editor_venue_details',
326
-                    ),
327
-                    'event_editor_event_datetimes_help_tab'            => array(
328
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
329
-                        'filename' => 'event_editor_event_datetimes',
330
-                    ),
331
-                    'event_editor_event_tickets_help_tab'              => array(
332
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
333
-                        'filename' => 'event_editor_event_tickets',
334
-                    ),
335
-                    'event_editor_event_registration_options_help_tab' => array(
336
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
337
-                        'filename' => 'event_editor_event_registration_options',
338
-                    ),
339
-                    'event_editor_tags_categories_help_tab'            => array(
340
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
341
-                        'filename' => 'event_editor_tags_categories',
342
-                    ),
343
-                    'event_editor_questions_registrants_help_tab'      => array(
344
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
345
-                        'filename' => 'event_editor_questions_registrants',
346
-                    ),
347
-                    'event_editor_save_new_event_help_tab'             => array(
348
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
349
-                        'filename' => 'event_editor_save_new_event',
350
-                    ),
351
-                    'event_editor_other_help_tab'                      => array(
352
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
353
-                        'filename' => 'event_editor_other',
354
-                    ),
355
-                ),
356
-                'help_tour'     => array(
357
-                    'Event_Editor_Help_Tour',
358
-                ),
359
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
360
-                'require_nonce' => false,
361
-            ),
362
-            'edit'                   => array(
363
-                'nav'           => array(
364
-                    'label'      => esc_html__('Edit Event', 'event_espresso'),
365
-                    'order'      => 5,
366
-                    'persistent' => false,
367
-                    'url'        => isset($this->_req_data['post'])
368
-                        ? EE_Admin_Page::add_query_args_and_nonce(
369
-                            array('post' => $this->_req_data['post'], 'action' => 'edit'),
370
-                            $this->_current_page_view_url
371
-                        )
372
-                        : $this->_admin_base_url,
373
-                ),
374
-                'metaboxes'     => array('_register_event_editor_meta_boxes'),
375
-                'help_tabs'     => array(
376
-                    'event_editor_help_tab'                            => array(
377
-                        'title'    => esc_html__('Event Editor', 'event_espresso'),
378
-                        'filename' => 'event_editor',
379
-                    ),
380
-                    'event_editor_title_richtexteditor_help_tab'       => array(
381
-                        'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
382
-                        'filename' => 'event_editor_title_richtexteditor',
383
-                    ),
384
-                    'event_editor_venue_details_help_tab'              => array(
385
-                        'title'    => esc_html__('Event Venue Details', 'event_espresso'),
386
-                        'filename' => 'event_editor_venue_details',
387
-                    ),
388
-                    'event_editor_event_datetimes_help_tab'            => array(
389
-                        'title'    => esc_html__('Event Datetimes', 'event_espresso'),
390
-                        'filename' => 'event_editor_event_datetimes',
391
-                    ),
392
-                    'event_editor_event_tickets_help_tab'              => array(
393
-                        'title'    => esc_html__('Event Tickets', 'event_espresso'),
394
-                        'filename' => 'event_editor_event_tickets',
395
-                    ),
396
-                    'event_editor_event_registration_options_help_tab' => array(
397
-                        'title'    => esc_html__('Event Registration Options', 'event_espresso'),
398
-                        'filename' => 'event_editor_event_registration_options',
399
-                    ),
400
-                    'event_editor_tags_categories_help_tab'            => array(
401
-                        'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
402
-                        'filename' => 'event_editor_tags_categories',
403
-                    ),
404
-                    'event_editor_questions_registrants_help_tab'      => array(
405
-                        'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
406
-                        'filename' => 'event_editor_questions_registrants',
407
-                    ),
408
-                    'event_editor_save_new_event_help_tab'             => array(
409
-                        'title'    => esc_html__('Save New Event', 'event_espresso'),
410
-                        'filename' => 'event_editor_save_new_event',
411
-                    ),
412
-                    'event_editor_other_help_tab'                      => array(
413
-                        'title'    => esc_html__('Event Other', 'event_espresso'),
414
-                        'filename' => 'event_editor_other',
415
-                    ),
416
-                ),
417
-                'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
418
-                'require_nonce' => false,
419
-            ),
420
-            'default_event_settings' => array(
421
-                'nav'           => array(
422
-                    'label' => esc_html__('Default Settings', 'event_espresso'),
423
-                    'order' => 40,
424
-                ),
425
-                'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
426
-                'labels'        => array(
427
-                    'publishbox' => esc_html__('Update Settings', 'event_espresso'),
428
-                ),
429
-                'help_tabs'     => array(
430
-                    'default_settings_help_tab'        => array(
431
-                        'title'    => esc_html__('Default Event Settings', 'event_espresso'),
432
-                        'filename' => 'events_default_settings',
433
-                    ),
434
-                    'default_settings_status_help_tab' => array(
435
-                        'title'    => esc_html__('Default Registration Status', 'event_espresso'),
436
-                        'filename' => 'events_default_settings_status',
437
-                    ),
438
-                    'default_maximum_tickets_help_tab' => array(
439
-                        'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
440
-                        'filename' => 'events_default_settings_max_tickets',
441
-                    ),
442
-                ),
443
-                'help_tour'     => array('Event_Default_Settings_Help_Tour'),
444
-                'require_nonce' => false,
445
-            ),
446
-            // template settings
447
-            'template_settings'      => array(
448
-                'nav'           => array(
449
-                    'label' => esc_html__('Templates', 'event_espresso'),
450
-                    'order' => 30,
451
-                ),
452
-                'metaboxes'     => $this->_default_espresso_metaboxes,
453
-                'help_tabs'     => array(
454
-                    'general_settings_templates_help_tab' => array(
455
-                        'title'    => esc_html__('Templates', 'event_espresso'),
456
-                        'filename' => 'general_settings_templates',
457
-                    ),
458
-                ),
459
-                'help_tour'     => array('Templates_Help_Tour'),
460
-                'require_nonce' => false,
461
-            ),
462
-            // event category stuff
463
-            'add_category'           => array(
464
-                'nav'           => array(
465
-                    'label'      => esc_html__('Add Category', 'event_espresso'),
466
-                    'order'      => 15,
467
-                    'persistent' => false,
468
-                ),
469
-                'help_tabs'     => array(
470
-                    'add_category_help_tab' => array(
471
-                        'title'    => esc_html__('Add New Event Category', 'event_espresso'),
472
-                        'filename' => 'events_add_category',
473
-                    ),
474
-                ),
475
-                'help_tour'     => array('Event_Add_Category_Help_Tour'),
476
-                'metaboxes'     => array('_publish_post_box'),
477
-                'require_nonce' => false,
478
-            ),
479
-            'edit_category'          => array(
480
-                'nav'           => array(
481
-                    'label'      => esc_html__('Edit Category', 'event_espresso'),
482
-                    'order'      => 15,
483
-                    'persistent' => false,
484
-                    'url'        => isset($this->_req_data['EVT_CAT_ID'])
485
-                        ? add_query_arg(
486
-                            array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
487
-                            $this->_current_page_view_url
488
-                        )
489
-                        : $this->_admin_base_url,
490
-                ),
491
-                'help_tabs'     => array(
492
-                    'edit_category_help_tab' => array(
493
-                        'title'    => esc_html__('Edit Event Category', 'event_espresso'),
494
-                        'filename' => 'events_edit_category',
495
-                    ),
496
-                ),
497
-                /*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
498
-                'metaboxes'     => array('_publish_post_box'),
499
-                'require_nonce' => false,
500
-            ),
501
-            'category_list'          => array(
502
-                'nav'           => array(
503
-                    'label' => esc_html__('Categories', 'event_espresso'),
504
-                    'order' => 20,
505
-                ),
506
-                'list_table'    => 'Event_Categories_Admin_List_Table',
507
-                'help_tabs'     => array(
508
-                    'events_categories_help_tab'                       => array(
509
-                        'title'    => esc_html__('Event Categories', 'event_espresso'),
510
-                        'filename' => 'events_categories',
511
-                    ),
512
-                    'events_categories_table_column_headings_help_tab' => array(
513
-                        'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
514
-                        'filename' => 'events_categories_table_column_headings',
515
-                    ),
516
-                    'events_categories_view_help_tab'                  => array(
517
-                        'title'    => esc_html__('Event Categories Views', 'event_espresso'),
518
-                        'filename' => 'events_categories_views',
519
-                    ),
520
-                    'events_categories_other_help_tab'                 => array(
521
-                        'title'    => esc_html__('Event Categories Other', 'event_espresso'),
522
-                        'filename' => 'events_categories_other',
523
-                    ),
524
-                ),
525
-                'help_tour'     => array(
526
-                    'Event_Categories_Help_Tour',
527
-                ),
528
-                'metaboxes'     => $this->_default_espresso_metaboxes,
529
-                'require_nonce' => false,
530
-            ),
531
-            'preview_deletion'           => array(
532
-                'nav'           => array(
533
-                    'label'      => esc_html__('Preview Deletion', 'event_espresso'),
534
-                    'order'      => 15,
535
-                    'persistent' => false,
536
-                ),
537
-                'require_nonce' => false
538
-            )
539
-        );
540
-    }
541
-
542
-
543
-    /**
544
-     * Used to register any global screen options if necessary for every route in this admin page group.
545
-     */
546
-    protected function _add_screen_options()
547
-    {
548
-    }
549
-
550
-
551
-    /**
552
-     * Implementing the screen options for the 'default' route.
553
-     */
554
-    protected function _add_screen_options_default()
555
-    {
556
-        $this->_per_page_screen_option();
557
-    }
558
-
559
-
560
-    /**
561
-     * Implementing screen options for the category list route.
562
-     */
563
-    protected function _add_screen_options_category_list()
564
-    {
565
-        $page_title = $this->_admin_page_title;
566
-        $this->_admin_page_title = esc_html__('Categories', 'event_espresso');
567
-        $this->_per_page_screen_option();
568
-        $this->_admin_page_title = $page_title;
569
-    }
570
-
571
-
572
-    /**
573
-     * Used to register any global feature pointers for the admin page group.
574
-     */
575
-    protected function _add_feature_pointers()
576
-    {
577
-    }
578
-
579
-
580
-    /**
581
-     * Registers and enqueues any global scripts and styles for the entire admin page group.
582
-     */
583
-    public function load_scripts_styles()
584
-    {
585
-        wp_register_style(
586
-            'events-admin-css',
587
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
588
-            array(),
589
-            EVENT_ESPRESSO_VERSION
590
-        );
591
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
592
-        wp_enqueue_style('events-admin-css');
593
-        wp_enqueue_style('ee-cat-admin');
594
-        // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
595
-        // registers for all views
596
-        // scripts
597
-        wp_register_script(
598
-            'event_editor_js',
599
-            EVENTS_ASSETS_URL . 'event_editor.js',
600
-            array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
601
-            EVENT_ESPRESSO_VERSION,
602
-            true
603
-        );
604
-    }
605
-
606
-
607
-    /**
608
-     * Enqueuing scripts and styles specific to this view
609
-     */
610
-    public function load_scripts_styles_create_new()
611
-    {
612
-        $this->load_scripts_styles_edit();
613
-    }
614
-
615
-
616
-    /**
617
-     * Enqueuing scripts and styles specific to this view
618
-     */
619
-    public function load_scripts_styles_edit()
620
-    {
621
-        // styles
622
-        wp_enqueue_style('espresso-ui-theme');
623
-        wp_register_style(
624
-            'event-editor-css',
625
-            EVENTS_ASSETS_URL . 'event-editor.css',
626
-            array('ee-admin-css'),
627
-            EVENT_ESPRESSO_VERSION
628
-        );
629
-        wp_enqueue_style('event-editor-css');
630
-        // scripts
631
-        wp_register_script(
632
-            'event-datetime-metabox',
633
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
634
-            array('event_editor_js', 'ee-datepicker'),
635
-            EVENT_ESPRESSO_VERSION
636
-        );
637
-        wp_enqueue_script('event-datetime-metabox');
638
-    }
639
-
640
-
641
-    /**
642
-     * Populating the _views property for the category list table view.
643
-     */
644
-    protected function _set_list_table_views_category_list()
645
-    {
646
-        $this->_views = array(
647
-            'all' => array(
648
-                'slug'        => 'all',
649
-                'label'       => esc_html__('All', 'event_espresso'),
650
-                'count'       => 0,
651
-                'bulk_action' => array(
652
-                    'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
653
-                ),
654
-            ),
655
-        );
656
-    }
657
-
658
-
659
-    /**
660
-     * For adding anything that fires on the admin_init hook for any route within this admin page group.
661
-     */
662
-    public function admin_init()
663
-    {
664
-        EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
665
-            'Do you really want to delete this image? Please remember to update your event to complete the removal.',
666
-            'event_espresso'
667
-        );
668
-    }
669
-
670
-
671
-    /**
672
-     * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
673
-     * group.
674
-     */
675
-    public function admin_notices()
676
-    {
677
-    }
678
-
679
-
680
-    /**
681
-     * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
682
-     * this admin page group.
683
-     */
684
-    public function admin_footer_scripts()
685
-    {
686
-    }
687
-
688
-
689
-    /**
690
-     * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
691
-     * warning (via EE_Error::add_error());
692
-     *
693
-     * @param  EE_Event $event Event object
694
-     * @param string    $req_type
695
-     * @return void
696
-     * @throws EE_Error
697
-     * @access public
698
-     */
699
-    public function verify_event_edit($event = null, $req_type = '')
700
-    {
701
-        // don't need to do this when processing
702
-        if (! empty($req_type)) {
703
-            return;
704
-        }
705
-        // no event?
706
-        if (empty($event)) {
707
-            // set event
708
-            $event = $this->_cpt_model_obj;
709
-        }
710
-        // STILL no event?
711
-        if (! $event instanceof EE_Event) {
712
-            return;
713
-        }
714
-        $orig_status = $event->status();
715
-        // first check if event is active.
716
-        if ($orig_status === EEM_Event::cancelled
717
-            || $orig_status === EEM_Event::postponed
718
-            || $event->is_expired()
719
-            || $event->is_inactive()
720
-        ) {
721
-            return;
722
-        }
723
-        // made it here so it IS active... next check that any of the tickets are sold.
724
-        if ($event->is_sold_out(true)) {
725
-            if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
726
-                EE_Error::add_attention(
727
-                    sprintf(
728
-                        esc_html__(
729
-                            'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
730
-                            'event_espresso'
731
-                        ),
732
-                        EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
733
-                    )
734
-                );
735
-            }
736
-            return;
737
-        } elseif ($orig_status === EEM_Event::sold_out) {
738
-            EE_Error::add_attention(
739
-                sprintf(
740
-                    esc_html__(
741
-                        'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
742
-                        'event_espresso'
743
-                    ),
744
-                    EEH_Template::pretty_status($event->status(), false, 'sentence')
745
-                )
746
-            );
747
-        }
748
-        // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
749
-        if (! $event->tickets_on_sale()) {
750
-            return;
751
-        }
752
-        // made it here so show warning
753
-        $this->_edit_event_warning();
754
-    }
755
-
756
-
757
-    /**
758
-     * This is the text used for when an event is being edited that is public and has tickets for sale.
759
-     * When needed, hook this into a EE_Error::add_error() notice.
760
-     *
761
-     * @access protected
762
-     * @return void
763
-     */
764
-    protected function _edit_event_warning()
765
-    {
766
-        // we don't want to add warnings during these requests
767
-        if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
768
-            return;
769
-        }
770
-        EE_Error::add_attention(
771
-            sprintf(
772
-                esc_html__(
773
-                    'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
774
-                    'event_espresso'
775
-                ),
776
-                '<a class="espresso-help-tab-lnk">',
777
-                '</a>'
778
-            )
779
-        );
780
-    }
781
-
782
-
783
-    /**
784
-     * When a user is creating a new event, notify them if they haven't set their timezone.
785
-     * Otherwise, do the normal logic
786
-     *
787
-     * @return string
788
-     * @throws \EE_Error
789
-     */
790
-    protected function _create_new_cpt_item()
791
-    {
792
-        $has_timezone_string = get_option('timezone_string');
793
-        // only nag them about setting their timezone if it's their first event, and they haven't already done it
794
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
795
-            EE_Error::add_attention(
796
-                sprintf(
797
-                    __(
798
-                        'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
799
-                        'event_espresso'
800
-                    ),
801
-                    '<br>',
802
-                    '<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
803
-                    . EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
804
-                    . '</select>',
805
-                    '<button class="button button-secondary timezone-submit">',
806
-                    '</button><span class="spinner"></span>'
807
-                ),
808
-                __FILE__,
809
-                __FUNCTION__,
810
-                __LINE__
811
-            );
812
-        }
813
-        return parent::_create_new_cpt_item();
814
-    }
815
-
816
-
817
-    /**
818
-     * Sets the _views property for the default route in this admin page group.
819
-     */
820
-    protected function _set_list_table_views_default()
821
-    {
822
-        $this->_views = array(
823
-            'all'   => array(
824
-                'slug'        => 'all',
825
-                'label'       => esc_html__('View All Events', 'event_espresso'),
826
-                'count'       => 0,
827
-                'bulk_action' => array(
828
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
829
-                ),
830
-            ),
831
-            'draft' => array(
832
-                'slug'        => 'draft',
833
-                'label'       => esc_html__('Draft', 'event_espresso'),
834
-                'count'       => 0,
835
-                'bulk_action' => array(
836
-                    'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
837
-                ),
838
-            ),
839
-        );
840
-        if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
841
-            $this->_views['trash'] = array(
842
-                'slug'        => 'trash',
843
-                'label'       => esc_html__('Trash', 'event_espresso'),
844
-                'count'       => 0,
845
-                'bulk_action' => array(
846
-                    'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
847
-                    'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
848
-                ),
849
-            );
850
-        }
851
-    }
852
-
853
-
854
-    /**
855
-     * Provides the legend item array for the default list table view.
856
-     *
857
-     * @return array
858
-     */
859
-    protected function _event_legend_items()
860
-    {
861
-        $items = array(
862
-            'view_details'   => array(
863
-                'class' => 'dashicons dashicons-search',
864
-                'desc'  => esc_html__('View Event', 'event_espresso'),
865
-            ),
866
-            'edit_event'     => array(
867
-                'class' => 'ee-icon ee-icon-calendar-edit',
868
-                'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
869
-            ),
870
-            'view_attendees' => array(
871
-                'class' => 'dashicons dashicons-groups',
872
-                'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
873
-            ),
874
-        );
875
-        $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
876
-        $statuses = array(
877
-            'sold_out_status'  => array(
878
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
879
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
880
-            ),
881
-            'active_status'    => array(
882
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
883
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
884
-            ),
885
-            'upcoming_status'  => array(
886
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
887
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
888
-            ),
889
-            'postponed_status' => array(
890
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
891
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
892
-            ),
893
-            'cancelled_status' => array(
894
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
895
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
896
-            ),
897
-            'expired_status'   => array(
898
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
899
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
900
-            ),
901
-            'inactive_status'  => array(
902
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
903
-                'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
904
-            ),
905
-        );
906
-        $statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
907
-        return array_merge($items, $statuses);
908
-    }
909
-
910
-
911
-    /**
912
-     * @return EEM_Event
913
-     */
914
-    private function _event_model()
915
-    {
916
-        if (! $this->_event_model instanceof EEM_Event) {
917
-            $this->_event_model = EE_Registry::instance()->load_model('Event');
918
-        }
919
-        return $this->_event_model;
920
-    }
921
-
922
-
923
-    /**
924
-     * Adds extra buttons to the WP CPT permalink field row.
925
-     * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
926
-     *
927
-     * @param  string $return    the current html
928
-     * @param  int    $id        the post id for the page
929
-     * @param  string $new_title What the title is
930
-     * @param  string $new_slug  what the slug is
931
-     * @return string            The new html string for the permalink area
932
-     */
933
-    public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
934
-    {
935
-        // make sure this is only when editing
936
-        if (! empty($id)) {
937
-            $post = get_post($id);
938
-            $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
939
-                       . esc_html__('Shortcode', 'event_espresso')
940
-                       . '</a> ';
941
-            $return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
942
-                       . $post->ID
943
-                       . ']">';
944
-        }
945
-        return $return;
946
-    }
947
-
948
-
949
-    /**
950
-     * _events_overview_list_table
951
-     * This contains the logic for showing the events_overview list
952
-     *
953
-     * @access protected
954
-     * @return void
955
-     * @throws \EE_Error
956
-     */
957
-    protected function _events_overview_list_table()
958
-    {
959
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
960
-        $this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
961
-            ? (array) $this->_template_args['after_list_table']
962
-            : array();
963
-        $this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
964
-                . EEH_Template::get_button_or_link(
965
-                    get_post_type_archive_link('espresso_events'),
966
-                    esc_html__("View Event Archive Page", "event_espresso"),
967
-                    'button'
968
-                );
969
-        $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
970
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
971
-            'create_new',
972
-            'add',
973
-            array(),
974
-            'add-new-h2'
975
-        );
976
-        $this->display_admin_list_table_page_with_no_sidebar();
977
-    }
978
-
979
-
980
-    /**
981
-     * this allows for extra misc actions in the default WP publish box
982
-     *
983
-     * @return void
984
-     */
985
-    public function extra_misc_actions_publish_box()
986
-    {
987
-        $this->_generate_publish_box_extra_content();
988
-    }
989
-
990
-
991
-    /**
992
-     * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
993
-     * saved.
994
-     * Typically you would use this to save any additional data.
995
-     * Keep in mind also that "save_post" runs on EVERY post update to the database.
996
-     * ALSO very important.  When a post transitions from scheduled to published,
997
-     * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
998
-     * other meta saves. So MAKE sure that you handle this accordingly.
999
-     *
1000
-     * @access protected
1001
-     * @abstract
1002
-     * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
1003
-     * @param  object $post    The post object of the cpt that was saved.
1004
-     * @return void
1005
-     * @throws \EE_Error
1006
-     */
1007
-    protected function _insert_update_cpt_item($post_id, $post)
1008
-    {
1009
-        if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1010
-            // get out we're not processing an event save.
1011
-            return;
1012
-        }
1013
-        $event_values = array(
1014
-            'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1015
-            'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1016
-            'EVT_additional_limit'            => min(
1017
-                apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1018
-                ! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1019
-            ),
1020
-            'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1021
-                ? $this->_req_data['EVT_default_registration_status']
1022
-                : EE_Registry::instance()->CFG->registration->default_STS_ID,
1023
-            'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1024
-            'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1025
-            'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1026
-                ? $this->_req_data['timezone_string'] : null,
1027
-            'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1028
-                ? $this->_req_data['externalURL'] : null,
1029
-            'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1030
-                ? $this->_req_data['event_phone'] : null,
1031
-        );
1032
-        // update event
1033
-        $success = $this->_event_model()->update_by_ID($event_values, $post_id);
1034
-        // get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1035
-        $get_one_where = array(
1036
-            $this->_event_model()->primary_key_name() => $post_id,
1037
-            'OR'                                      => array(
1038
-                'status'   => $post->post_status,
1039
-                // if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1040
-                // but the returned object here has a status of "publish", so use the original post status as well
1041
-                'status*1' => $this->_req_data['original_post_status'],
1042
-            ),
1043
-        );
1044
-        $event = $this->_event_model()->get_one(array($get_one_where));
1045
-        // the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1046
-        $event_update_callbacks = apply_filters(
1047
-            'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1048
-            array(
1049
-                array($this, '_default_venue_update'),
1050
-                array($this, '_default_tickets_update'),
1051
-            )
1052
-        );
1053
-        $att_success = true;
1054
-        foreach ($event_update_callbacks as $e_callback) {
1055
-            $_success = is_callable($e_callback)
1056
-                ? call_user_func($e_callback, $event, $this->_req_data)
1057
-                : false;
1058
-            // if ANY of these updates fail then we want the appropriate global error message
1059
-            $att_success = ! $att_success ? $att_success : $_success;
1060
-        }
1061
-        // any errors?
1062
-        if ($success && false === $att_success) {
1063
-            EE_Error::add_error(
1064
-                esc_html__(
1065
-                    'Event Details saved successfully but something went wrong with saving attachments.',
1066
-                    'event_espresso'
1067
-                ),
1068
-                __FILE__,
1069
-                __FUNCTION__,
1070
-                __LINE__
1071
-            );
1072
-        } elseif ($success === false) {
1073
-            EE_Error::add_error(
1074
-                esc_html__('Event Details did not save successfully.', 'event_espresso'),
1075
-                __FILE__,
1076
-                __FUNCTION__,
1077
-                __LINE__
1078
-            );
1079
-        }
1080
-    }
1081
-
1082
-
1083
-    /**
1084
-     * @see parent::restore_item()
1085
-     * @param int $post_id
1086
-     * @param int $revision_id
1087
-     */
1088
-    protected function _restore_cpt_item($post_id, $revision_id)
1089
-    {
1090
-        // copy existing event meta to new post
1091
-        $post_evt = $this->_event_model()->get_one_by_ID($post_id);
1092
-        if ($post_evt instanceof EE_Event) {
1093
-            // meta revision restore
1094
-            $post_evt->restore_revision($revision_id);
1095
-            // related objs restore
1096
-            $post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1097
-        }
1098
-    }
1099
-
1100
-
1101
-    /**
1102
-     * Attach the venue to the Event
1103
-     *
1104
-     * @param  \EE_Event $evtobj Event Object to add the venue to
1105
-     * @param  array     $data   The request data from the form
1106
-     * @return bool           Success or fail.
1107
-     */
1108
-    protected function _default_venue_update(\EE_Event $evtobj, $data)
1109
-    {
1110
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1111
-        $venue_model = EE_Registry::instance()->load_model('Venue');
1112
-        $rows_affected = null;
1113
-        $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1114
-        // very important.  If we don't have a venue name...
1115
-        // then we'll get out because not necessary to create empty venue
1116
-        if (empty($data['venue_title'])) {
1117
-            return false;
1118
-        }
1119
-        $venue_array = array(
1120
-            'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1121
-            'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1122
-            'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1123
-            'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1124
-            'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1125
-                : null,
1126
-            'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1127
-            'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1128
-            'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1129
-            'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1130
-            'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1131
-            'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1132
-            'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1133
-            'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1134
-            'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1135
-            'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1136
-            'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1137
-            'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1138
-            'status'              => 'publish',
1139
-        );
1140
-        // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1141
-        if (! empty($venue_id)) {
1142
-            $update_where = array($venue_model->primary_key_name() => $venue_id);
1143
-            $rows_affected = $venue_model->update($venue_array, array($update_where));
1144
-            // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1145
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1146
-            return $rows_affected > 0 ? true : false;
1147
-        } else {
1148
-            // we insert the venue
1149
-            $venue_id = $venue_model->insert($venue_array);
1150
-            $evtobj->_add_relation_to($venue_id, 'Venue');
1151
-            return ! empty($venue_id) ? true : false;
1152
-        }
1153
-        // when we have the ancestor come in it's already been handled by the revision save.
1154
-    }
1155
-
1156
-
1157
-    /**
1158
-     * Handles saving everything related to Tickets (datetimes, tickets, prices)
1159
-     *
1160
-     * @param  EE_Event $evtobj The Event object we're attaching data to
1161
-     * @param  array    $data   The request data from the form
1162
-     * @return array
1163
-     */
1164
-    protected function _default_tickets_update(EE_Event $evtobj, $data)
1165
-    {
1166
-        $success = true;
1167
-        $saved_dtt = null;
1168
-        $saved_tickets = array();
1169
-        $incoming_date_formats = array('Y-m-d', 'h:i a');
1170
-        foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1171
-            // trim all values to ensure any excess whitespace is removed.
1172
-            $dtt = array_map('trim', $dtt);
1173
-            $dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1174
-                : $dtt['DTT_EVT_start'];
1175
-            $datetime_values = array(
1176
-                'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1177
-                'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1178
-                'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1179
-                'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1180
-                'DTT_order'     => $row,
1181
-            );
1182
-            // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1183
-            if (! empty($dtt['DTT_ID'])) {
1184
-                $DTM = EE_Registry::instance()
1185
-                                  ->load_model('Datetime', array($evtobj->get_timezone()))
1186
-                                  ->get_one_by_ID($dtt['DTT_ID']);
1187
-                $DTM->set_date_format($incoming_date_formats[0]);
1188
-                $DTM->set_time_format($incoming_date_formats[1]);
1189
-                foreach ($datetime_values as $field => $value) {
1190
-                    $DTM->set($field, $value);
1191
-                }
1192
-                // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1193
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1194
-            } else {
1195
-                $DTM = EE_Registry::instance()->load_class(
1196
-                    'Datetime',
1197
-                    array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1198
-                    false,
1199
-                    false
1200
-                );
1201
-                foreach ($datetime_values as $field => $value) {
1202
-                    $DTM->set($field, $value);
1203
-                }
1204
-            }
1205
-            $DTM->save();
1206
-            $DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1207
-            // load DTT helper
1208
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1209
-            if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1210
-                $DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1211
-                $DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1212
-                $DTT->save();
1213
-            }
1214
-            // now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1215
-            $saved_dtt = $DTT;
1216
-            $success = ! $success ? $success : $DTT;
1217
-            // if ANY of these updates fail then we want the appropriate global error message.
1218
-            // //todo this is actually sucky we need a better error message but this is what it is for now.
1219
-        }
1220
-        // no dtts get deleted so we don't do any of that logic here.
1221
-        // update tickets next
1222
-        $old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1223
-        foreach ($data['edit_tickets'] as $row => $tkt) {
1224
-            $incoming_date_formats = array('Y-m-d', 'h:i a');
1225
-            $update_prices = false;
1226
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1227
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1228
-            // trim inputs to ensure any excess whitespace is removed.
1229
-            $tkt = array_map('trim', $tkt);
1230
-            if (empty($tkt['TKT_start_date'])) {
1231
-                // let's use now in the set timezone.
1232
-                $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1233
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1234
-            }
1235
-            if (empty($tkt['TKT_end_date'])) {
1236
-                // use the start date of the first datetime
1237
-                $dtt = $evtobj->first_datetime();
1238
-                $tkt['TKT_end_date'] = $dtt->start_date_and_time(
1239
-                    $incoming_date_formats[0],
1240
-                    $incoming_date_formats[1]
1241
-                );
1242
-            }
1243
-            $TKT_values = array(
1244
-                'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1245
-                'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1246
-                'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1247
-                'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1248
-                'TKT_start_date'  => $tkt['TKT_start_date'],
1249
-                'TKT_end_date'    => $tkt['TKT_end_date'],
1250
-                'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1251
-                'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1252
-                'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1253
-                'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1254
-                'TKT_row'         => $row,
1255
-                'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1256
-                'TKT_price'       => $ticket_price,
1257
-            );
1258
-            // if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1259
-            if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1260
-                $TKT_values['TKT_ID'] = 0;
1261
-                $TKT_values['TKT_is_default'] = 0;
1262
-                $TKT_values['TKT_price'] = $ticket_price;
1263
-                $update_prices = true;
1264
-            }
1265
-            // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1266
-            // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1267
-            // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1268
-            if (! empty($tkt['TKT_ID'])) {
1269
-                $TKT = EE_Registry::instance()
1270
-                                  ->load_model('Ticket', array($evtobj->get_timezone()))
1271
-                                  ->get_one_by_ID($tkt['TKT_ID']);
1272
-                if ($TKT instanceof EE_Ticket) {
1273
-                    $ticket_sold = $TKT->count_related(
1274
-                        'Registration',
1275
-                        array(
1276
-                            array(
1277
-                                'STS_ID' => array(
1278
-                                    'NOT IN',
1279
-                                    array(EEM_Registration::status_id_incomplete),
1280
-                                ),
1281
-                            ),
1282
-                        )
1283
-                    ) > 0 ? true : false;
1284
-                    // let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1285
-                    $create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1286
-                                      && ! $TKT->get('TKT_deleted');
1287
-                    $TKT->set_date_format($incoming_date_formats[0]);
1288
-                    $TKT->set_time_format($incoming_date_formats[1]);
1289
-                    // set new values
1290
-                    foreach ($TKT_values as $field => $value) {
1291
-                        if ($field == 'TKT_qty') {
1292
-                            $TKT->set_qty($value);
1293
-                        } else {
1294
-                            $TKT->set($field, $value);
1295
-                        }
1296
-                    }
1297
-                    // if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1298
-                    if ($create_new_TKT) {
1299
-                        // archive the old ticket first
1300
-                        $TKT->set('TKT_deleted', 1);
1301
-                        $TKT->save();
1302
-                        // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1303
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1304
-                        // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1305
-                        $TKT = clone $TKT;
1306
-                        $TKT->set('TKT_ID', 0);
1307
-                        $TKT->set('TKT_deleted', 0);
1308
-                        $TKT->set('TKT_price', $ticket_price);
1309
-                        $TKT->set('TKT_sold', 0);
1310
-                        // now we need to make sure that $new prices are created as well and attached to new ticket.
1311
-                        $update_prices = true;
1312
-                    }
1313
-                    // make sure price is set if it hasn't been already
1314
-                    $TKT->set('TKT_price', $ticket_price);
1315
-                }
1316
-            } else {
1317
-                // no TKT_id so a new TKT
1318
-                $TKT_values['TKT_price'] = $ticket_price;
1319
-                $TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1320
-                if ($TKT instanceof EE_Ticket) {
1321
-                    // need to reset values to properly account for the date formats
1322
-                    $TKT->set_date_format($incoming_date_formats[0]);
1323
-                    $TKT->set_time_format($incoming_date_formats[1]);
1324
-                    $TKT->set_timezone($evtobj->get_timezone());
1325
-                    // set new values
1326
-                    foreach ($TKT_values as $field => $value) {
1327
-                        if ($field == 'TKT_qty') {
1328
-                            $TKT->set_qty($value);
1329
-                        } else {
1330
-                            $TKT->set($field, $value);
1331
-                        }
1332
-                    }
1333
-                    $update_prices = true;
1334
-                }
1335
-            }
1336
-            // cap ticket qty by datetime reg limits
1337
-            $TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1338
-            // update ticket.
1339
-            $TKT->save();
1340
-            // before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1341
-            if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1342
-                $TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1343
-                $TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1344
-                $TKT->save();
1345
-            }
1346
-            // initially let's add the ticket to the dtt
1347
-            $saved_dtt->_add_relation_to($TKT, 'Ticket');
1348
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1349
-            // add prices to ticket
1350
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1351
-        }
1352
-        // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1353
-        $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1354
-        $tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1355
-        foreach ($tickets_removed as $id) {
1356
-            $id = absint($id);
1357
-            // get the ticket for this id
1358
-            $tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1359
-            // need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1360
-            $dtts = $tkt_to_remove->get_many_related('Datetime');
1361
-            foreach ($dtts as $dtt) {
1362
-                $tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1363
-            }
1364
-            // need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1365
-            $tkt_to_remove->delete_related_permanently('Price');
1366
-            // finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1367
-            $tkt_to_remove->delete_permanently();
1368
-        }
1369
-        return array($saved_dtt, $saved_tickets);
1370
-    }
1371
-
1372
-
1373
-    /**
1374
-     * This attaches a list of given prices to a ticket.
1375
-     * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1376
-     * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1377
-     * price info and prices are automatically "archived" via the ticket.
1378
-     *
1379
-     * @access  private
1380
-     * @param array     $prices     Array of prices from the form.
1381
-     * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1382
-     * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1383
-     * @return  void
1384
-     */
1385
-    private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1386
-    {
1387
-        foreach ($prices as $row => $prc) {
1388
-            $PRC_values = array(
1389
-                'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1390
-                'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1391
-                'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1392
-                'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1393
-                'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1394
-                'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1395
-                'PRC_order'      => $row,
1396
-            );
1397
-            if ($new_prices || empty($PRC_values['PRC_ID'])) {
1398
-                $PRC_values['PRC_ID'] = 0;
1399
-                $PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1400
-            } else {
1401
-                $PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1402
-                // update this price with new values
1403
-                foreach ($PRC_values as $field => $newprc) {
1404
-                    $PRC->set($field, $newprc);
1405
-                }
1406
-                $PRC->save();
1407
-            }
1408
-            $ticket->_add_relation_to($PRC, 'Price');
1409
-        }
1410
-    }
1411
-
1412
-
1413
-    /**
1414
-     * Add in our autosave ajax handlers
1415
-     *
1416
-     */
1417
-    protected function _ee_autosave_create_new()
1418
-    {
1419
-    }
1420
-
1421
-
1422
-    /**
1423
-     * More autosave handlers.
1424
-     */
1425
-    protected function _ee_autosave_edit()
1426
-    {
1427
-        return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1428
-    }
1429
-
1430
-
1431
-    /**
1432
-     *    _generate_publish_box_extra_content
1433
-     */
1434
-    private function _generate_publish_box_extra_content()
1435
-    {
1436
-        // load formatter helper
1437
-        // args for getting related registrations
1438
-        $approved_query_args = array(
1439
-            array(
1440
-                'REG_deleted' => 0,
1441
-                'STS_ID'      => EEM_Registration::status_id_approved,
1442
-            ),
1443
-        );
1444
-        $not_approved_query_args = array(
1445
-            array(
1446
-                'REG_deleted' => 0,
1447
-                'STS_ID'      => EEM_Registration::status_id_not_approved,
1448
-            ),
1449
-        );
1450
-        $pending_payment_query_args = array(
1451
-            array(
1452
-                'REG_deleted' => 0,
1453
-                'STS_ID'      => EEM_Registration::status_id_pending_payment,
1454
-            ),
1455
-        );
1456
-        // publish box
1457
-        $publish_box_extra_args = array(
1458
-            'view_approved_reg_url'        => add_query_arg(
1459
-                array(
1460
-                    'action'      => 'default',
1461
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1462
-                    '_reg_status' => EEM_Registration::status_id_approved,
1463
-                ),
1464
-                REG_ADMIN_URL
1465
-            ),
1466
-            'view_not_approved_reg_url'    => add_query_arg(
1467
-                array(
1468
-                    'action'      => 'default',
1469
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1470
-                    '_reg_status' => EEM_Registration::status_id_not_approved,
1471
-                ),
1472
-                REG_ADMIN_URL
1473
-            ),
1474
-            'view_pending_payment_reg_url' => add_query_arg(
1475
-                array(
1476
-                    'action'      => 'default',
1477
-                    'event_id'    => $this->_cpt_model_obj->ID(),
1478
-                    '_reg_status' => EEM_Registration::status_id_pending_payment,
1479
-                ),
1480
-                REG_ADMIN_URL
1481
-            ),
1482
-            'approved_regs'                => $this->_cpt_model_obj->count_related(
1483
-                'Registration',
1484
-                $approved_query_args
1485
-            ),
1486
-            'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1487
-                'Registration',
1488
-                $not_approved_query_args
1489
-            ),
1490
-            'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1491
-                'Registration',
1492
-                $pending_payment_query_args
1493
-            ),
1494
-            'misc_pub_section_class'       => apply_filters(
1495
-                'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1496
-                'misc-pub-section'
1497
-            ),
1498
-        );
1499
-        ob_start();
1500
-        do_action(
1501
-            'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1502
-            $this->_cpt_model_obj
1503
-        );
1504
-        $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1505
-        // load template
1506
-        EEH_Template::display_template(
1507
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1508
-            $publish_box_extra_args
1509
-        );
1510
-    }
1511
-
1512
-
1513
-    /**
1514
-     * @return EE_Event
1515
-     */
1516
-    public function get_event_object()
1517
-    {
1518
-        return $this->_cpt_model_obj;
1519
-    }
1520
-
1521
-
1522
-
1523
-
1524
-    /** METABOXES * */
1525
-    /**
1526
-     * _register_event_editor_meta_boxes
1527
-     * add all metaboxes related to the event_editor
1528
-     *
1529
-     * @return void
1530
-     */
1531
-    protected function _register_event_editor_meta_boxes()
1532
-    {
1533
-        $this->verify_cpt_object();
1534
-        add_meta_box(
1535
-            'espresso_event_editor_tickets',
1536
-            esc_html__('Event Datetime & Ticket', 'event_espresso'),
1537
-            array($this, 'ticket_metabox'),
1538
-            $this->page_slug,
1539
-            'normal',
1540
-            'high'
1541
-        );
1542
-        add_meta_box(
1543
-            'espresso_event_editor_event_options',
1544
-            esc_html__('Event Registration Options', 'event_espresso'),
1545
-            array($this, 'registration_options_meta_box'),
1546
-            $this->page_slug,
1547
-            'side',
1548
-            'default'
1549
-        );
1550
-        // NOTE: if you're looking for other metaboxes in here,
1551
-        // where a metabox has a related management page in the admin
1552
-        // you will find it setup in the related management page's "_Hooks" file.
1553
-        // i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1554
-    }
1555
-
1556
-
1557
-    /**
1558
-     * @throws DomainException
1559
-     * @throws EE_Error
1560
-     */
1561
-    public function ticket_metabox()
1562
-    {
1563
-        $existing_datetime_ids = $existing_ticket_ids = array();
1564
-        // defaults for template args
1565
-        $template_args = array(
1566
-            'existing_datetime_ids'    => '',
1567
-            'event_datetime_help_link' => '',
1568
-            'ticket_options_help_link' => '',
1569
-            'time'                     => null,
1570
-            'ticket_rows'              => '',
1571
-            'existing_ticket_ids'      => '',
1572
-            'total_ticket_rows'        => 1,
1573
-            'ticket_js_structure'      => '',
1574
-            'trash_icon'               => 'ee-lock-icon',
1575
-            'disabled'                 => '',
1576
-        );
1577
-        $event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1578
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1579
-        /**
1580
-         * 1. Start with retrieving Datetimes
1581
-         * 2. Fore each datetime get related tickets
1582
-         * 3. For each ticket get related prices
1583
-         */
1584
-        $times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1585
-        /** @type EE_Datetime $first_datetime */
1586
-        $first_datetime = reset($times);
1587
-        // do we get related tickets?
1588
-        if ($first_datetime instanceof EE_Datetime
1589
-            && $first_datetime->ID() !== 0
1590
-        ) {
1591
-            $existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1592
-            $template_args['time'] = $first_datetime;
1593
-            $related_tickets = $first_datetime->tickets(
1594
-                array(
1595
-                    array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1596
-                    'default_where_conditions' => 'none',
1597
-                )
1598
-            );
1599
-            if (! empty($related_tickets)) {
1600
-                $template_args['total_ticket_rows'] = count($related_tickets);
1601
-                $row = 0;
1602
-                foreach ($related_tickets as $ticket) {
1603
-                    $existing_ticket_ids[] = $ticket->get('TKT_ID');
1604
-                    $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1605
-                    $row++;
1606
-                }
1607
-            } else {
1608
-                $template_args['total_ticket_rows'] = 1;
1609
-                /** @type EE_Ticket $ticket */
1610
-                $ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1611
-                $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1612
-            }
1613
-        } else {
1614
-            $template_args['time'] = $times[0];
1615
-            /** @type EE_Ticket $ticket */
1616
-            $ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1617
-            $template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1618
-            // NOTE: we're just sending the first default row
1619
-            // (decaf can't manage default tickets so this should be sufficient);
1620
-        }
1621
-        $template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1622
-            'event_editor_event_datetimes_help_tab'
1623
-        );
1624
-        $template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1625
-        $template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1626
-        $template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1627
-        $template_args['ticket_js_structure'] = $this->_get_ticket_row(
1628
-            EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1629
-            true
1630
-        );
1631
-        $template = apply_filters(
1632
-            'FHEE__Events_Admin_Page__ticket_metabox__template',
1633
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1634
-        );
1635
-        EEH_Template::display_template($template, $template_args);
1636
-    }
1637
-
1638
-
1639
-    /**
1640
-     * Setup an individual ticket form for the decaf event editor page
1641
-     *
1642
-     * @access private
1643
-     * @param  EE_Ticket $ticket   the ticket object
1644
-     * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1645
-     * @param int        $row
1646
-     * @return string generated html for the ticket row.
1647
-     */
1648
-    private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1649
-    {
1650
-        $template_args = array(
1651
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1652
-            'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1653
-                : '',
1654
-            'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1655
-            'TKT_ID'              => $ticket->get('TKT_ID'),
1656
-            'TKT_name'            => $ticket->get('TKT_name'),
1657
-            'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1658
-            'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1659
-            'TKT_is_default'      => $ticket->get('TKT_is_default'),
1660
-            'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1661
-            'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1662
-            'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1663
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1664
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1665
-                ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1666
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1667
-                : ' disabled=disabled',
1668
-        );
1669
-        $price = $ticket->ID() !== 0
1670
-            ? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1671
-            : EE_Registry::instance()->load_model('Price')->create_default_object();
1672
-        $price_args = array(
1673
-            'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1674
-            'PRC_amount'            => $price->get('PRC_amount'),
1675
-            'PRT_ID'                => $price->get('PRT_ID'),
1676
-            'PRC_ID'                => $price->get('PRC_ID'),
1677
-            'PRC_is_default'        => $price->get('PRC_is_default'),
1678
-        );
1679
-        // make sure we have default start and end dates if skeleton
1680
-        // handle rows that should NOT be empty
1681
-        if (empty($template_args['TKT_start_date'])) {
1682
-            // if empty then the start date will be now.
1683
-            $template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1684
-        }
1685
-        if (empty($template_args['TKT_end_date'])) {
1686
-            // get the earliest datetime (if present);
1687
-            $earliest_dtt = $this->_cpt_model_obj->ID() > 0
1688
-                ? $this->_cpt_model_obj->get_first_related(
1689
-                    'Datetime',
1690
-                    array('order_by' => array('DTT_EVT_start' => 'ASC'))
1691
-                )
1692
-                : null;
1693
-            if (! empty($earliest_dtt)) {
1694
-                $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1695
-            } else {
1696
-                $template_args['TKT_end_date'] = date(
1697
-                    'Y-m-d h:i a',
1698
-                    mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1699
-                );
1700
-            }
1701
-        }
1702
-        $template_args = array_merge($template_args, $price_args);
1703
-        $template = apply_filters(
1704
-            'FHEE__Events_Admin_Page__get_ticket_row__template',
1705
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1706
-            $ticket
1707
-        );
1708
-        return EEH_Template::display_template($template, $template_args, true);
1709
-    }
1710
-
1711
-
1712
-    /**
1713
-     * @throws DomainException
1714
-     */
1715
-    public function registration_options_meta_box()
1716
-    {
1717
-        $yes_no_values = array(
1718
-            array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1719
-            array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1720
-        );
1721
-        $default_reg_status_values = EEM_Registration::reg_status_array(
1722
-            array(
1723
-                EEM_Registration::status_id_cancelled,
1724
-                EEM_Registration::status_id_declined,
1725
-                EEM_Registration::status_id_incomplete,
1726
-            ),
1727
-            true
1728
-        );
1729
-        // $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1730
-        $template_args['_event'] = $this->_cpt_model_obj;
1731
-        $template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1732
-        $template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1733
-        $template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1734
-            'default_reg_status',
1735
-            $default_reg_status_values,
1736
-            $this->_cpt_model_obj->default_registration_status()
1737
-        );
1738
-        $template_args['display_description'] = EEH_Form_Fields::select_input(
1739
-            'display_desc',
1740
-            $yes_no_values,
1741
-            $this->_cpt_model_obj->display_description()
1742
-        );
1743
-        $template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1744
-            'display_ticket_selector',
1745
-            $yes_no_values,
1746
-            $this->_cpt_model_obj->display_ticket_selector(),
1747
-            '',
1748
-            '',
1749
-            false
1750
-        );
1751
-        $template_args['additional_registration_options'] = apply_filters(
1752
-            'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1753
-            '',
1754
-            $template_args,
1755
-            $yes_no_values,
1756
-            $default_reg_status_values
1757
-        );
1758
-        EEH_Template::display_template(
1759
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1760
-            $template_args
1761
-        );
1762
-    }
1763
-
1764
-
1765
-    /**
1766
-     * _get_events()
1767
-     * This method simply returns all the events (for the given _view and paging)
1768
-     *
1769
-     * @access public
1770
-     * @param int  $per_page     count of items per page (20 default);
1771
-     * @param int  $current_page what is the current page being viewed.
1772
-     * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1773
-     *                           If FALSE then we return an array of event objects
1774
-     *                           that match the given _view and paging parameters.
1775
-     * @return array an array of event objects.
1776
-     */
1777
-    public function get_events($per_page = 10, $current_page = 1, $count = false)
1778
-    {
1779
-        $EEME = $this->_event_model();
1780
-        $offset = ($current_page - 1) * $per_page;
1781
-        $limit = $count ? null : $offset . ',' . $per_page;
1782
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1783
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1784
-        if (isset($this->_req_data['month_range'])) {
1785
-            $pieces = explode(' ', $this->_req_data['month_range'], 3);
1786
-            // simulate the FIRST day of the month, that fixes issues for months like February
1787
-            // where PHP doesn't know what to assume for date.
1788
-            // @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1789
-            $month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1790
-            $year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1791
-        }
1792
-        $where = array();
1793
-        $status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1794
-        // determine what post_status our condition will have for the query.
1795
-        switch ($status) {
1796
-            case 'month':
1797
-            case 'today':
1798
-            case null:
1799
-            case 'all':
1800
-                break;
1801
-            case 'draft':
1802
-                $where['status'] = array('IN', array('draft', 'auto-draft'));
1803
-                break;
1804
-            default:
1805
-                $where['status'] = $status;
1806
-        }
1807
-        // categories?
1808
-        $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1809
-            ? $this->_req_data['EVT_CAT'] : null;
1810
-        if (! empty($category)) {
1811
-            $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1812
-            $where['Term_Taxonomy.term_id'] = $category;
1813
-        }
1814
-        // date where conditions
1815
-        $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1816
-        if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1817
-            $DateTime = new DateTime(
1818
-                $year_r . '-' . $month_r . '-01 00:00:00',
1819
-                new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1820
-            );
1821
-            $start = $DateTime->format(implode(' ', $start_formats));
1822
-            $end = $DateTime->setDate(
1823
-                $year_r,
1824
-                $month_r,
1825
-                $DateTime
1826
-                    ->format('t')
1827
-            )->setTime(23, 59, 59)
1828
-                            ->format(implode(' ', $start_formats));
1829
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1830
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1831
-            $DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1832
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1833
-            $end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1834
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1835
-        } elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1836
-            $now = date('Y-m-01');
1837
-            $DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1838
-            $start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1839
-            $end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1840
-                            ->setTime(23, 59, 59)
1841
-                            ->format(implode(' ', $start_formats));
1842
-            $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1843
-        }
1844
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1845
-            $where['EVT_wp_user'] = get_current_user_id();
1846
-        } else {
1847
-            if (! isset($where['status'])) {
1848
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1849
-                    $where['OR'] = array(
1850
-                        'status*restrict_private' => array('!=', 'private'),
1851
-                        'AND'                     => array(
1852
-                            'status*inclusive' => array('=', 'private'),
1853
-                            'EVT_wp_user'      => get_current_user_id(),
1854
-                        ),
1855
-                    );
1856
-                }
1857
-            }
1858
-        }
1859
-        if (isset($this->_req_data['EVT_wp_user'])) {
1860
-            if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1861
-                && EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1862
-            ) {
1863
-                $where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1864
-            }
1865
-        }
1866
-        // search query handling
1867
-        if (isset($this->_req_data['s'])) {
1868
-            $search_string = '%' . $this->_req_data['s'] . '%';
1869
-            $where['OR'] = array(
1870
-                'EVT_name'       => array('LIKE', $search_string),
1871
-                'EVT_desc'       => array('LIKE', $search_string),
1872
-                'EVT_short_desc' => array('LIKE', $search_string),
1873
-            );
1874
-        }
1875
-        // filter events by venue.
1876
-        if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1877
-            $where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1878
-        }
1879
-        $where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1880
-        $query_params = apply_filters(
1881
-            'FHEE__Events_Admin_Page__get_events__query_params',
1882
-            array(
1883
-                $where,
1884
-                'limit'    => $limit,
1885
-                'order_by' => $orderby,
1886
-                'order'    => $order,
1887
-                'group_by' => 'EVT_ID',
1888
-            ),
1889
-            $this->_req_data
1890
-        );
1891
-        // let's first check if we have special requests coming in.
1892
-        if (isset($this->_req_data['active_status'])) {
1893
-            switch ($this->_req_data['active_status']) {
1894
-                case 'upcoming':
1895
-                    return $EEME->get_upcoming_events($query_params, $count);
1896
-                    break;
1897
-                case 'expired':
1898
-                    return $EEME->get_expired_events($query_params, $count);
1899
-                    break;
1900
-                case 'active':
1901
-                    return $EEME->get_active_events($query_params, $count);
1902
-                    break;
1903
-                case 'inactive':
1904
-                    return $EEME->get_inactive_events($query_params, $count);
1905
-                    break;
1906
-            }
1907
-        }
1908
-
1909
-        $events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1910
-        return $events;
1911
-    }
1912
-
1913
-
1914
-    /**
1915
-     * handling for WordPress CPT actions (trash, restore, delete)
1916
-     *
1917
-     * @param string $post_id
1918
-     */
1919
-    public function trash_cpt_item($post_id)
1920
-    {
1921
-        $this->_req_data['EVT_ID'] = $post_id;
1922
-        $this->_trash_or_restore_event('trash', false);
1923
-    }
1924
-
1925
-
1926
-    /**
1927
-     * @param string $post_id
1928
-     */
1929
-    public function restore_cpt_item($post_id)
1930
-    {
1931
-        $this->_req_data['EVT_ID'] = $post_id;
1932
-        $this->_trash_or_restore_event('draft', false);
1933
-    }
1934
-
1935
-
1936
-    /**
1937
-     * @param string $post_id
1938
-     */
1939
-    public function delete_cpt_item($post_id)
1940
-    {
1941
-        throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
1942
-        $this->_req_data['EVT_ID'] = $post_id;
1943
-        $this->_delete_event();
1944
-    }
1945
-
1946
-
1947
-    /**
1948
-     * _trash_or_restore_event
1949
-     *
1950
-     * @access protected
1951
-     * @param  string $event_status
1952
-     * @param bool    $redirect_after
1953
-     */
1954
-    protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1955
-    {
1956
-        // determine the event id and set to array.
1957
-        $EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1958
-        // loop thru events
1959
-        if ($EVT_ID) {
1960
-            // clean status
1961
-            $event_status = sanitize_key($event_status);
1962
-            // grab status
1963
-            if (! empty($event_status)) {
1964
-                $success = $this->_change_event_status($EVT_ID, $event_status);
1965
-            } else {
1966
-                $success = false;
1967
-                $msg = esc_html__(
1968
-                    'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1969
-                    'event_espresso'
1970
-                );
1971
-                EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1972
-            }
1973
-        } else {
1974
-            $success = false;
1975
-            $msg = esc_html__(
1976
-                'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1977
-                'event_espresso'
1978
-            );
1979
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1980
-        }
1981
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1982
-        if ($redirect_after) {
1983
-            $this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1984
-        }
1985
-    }
1986
-
1987
-
1988
-    /**
1989
-     * _trash_or_restore_events
1990
-     *
1991
-     * @access protected
1992
-     * @param  string $event_status
1993
-     * @return void
1994
-     */
1995
-    protected function _trash_or_restore_events($event_status = 'trash')
1996
-    {
1997
-        // clean status
1998
-        $event_status = sanitize_key($event_status);
1999
-        // grab status
2000
-        if (! empty($event_status)) {
2001
-            $success = true;
2002
-            // determine the event id and set to array.
2003
-            $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2004
-            // loop thru events
2005
-            foreach ($EVT_IDs as $EVT_ID) {
2006
-                if ($EVT_ID = absint($EVT_ID)) {
2007
-                    $results = $this->_change_event_status($EVT_ID, $event_status);
2008
-                    $success = $results !== false ? $success : false;
2009
-                } else {
2010
-                    $msg = sprintf(
2011
-                        esc_html__(
2012
-                            'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2013
-                            'event_espresso'
2014
-                        ),
2015
-                        $EVT_ID
2016
-                    );
2017
-                    EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2018
-                    $success = false;
2019
-                }
2020
-            }
2021
-        } else {
2022
-            $success = false;
2023
-            $msg = esc_html__(
2024
-                'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2025
-                'event_espresso'
2026
-            );
2027
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2028
-        }
2029
-        // in order to force a pluralized result message we need to send back a success status greater than 1
2030
-        $success = $success ? 2 : false;
2031
-        $action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2032
-        $this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2033
-    }
2034
-
2035
-
2036
-    /**
2037
-     * _trash_or_restore_events
2038
-     *
2039
-     * @access  private
2040
-     * @param  int    $EVT_ID
2041
-     * @param  string $event_status
2042
-     * @return bool
2043
-     */
2044
-    private function _change_event_status($EVT_ID = 0, $event_status = '')
2045
-    {
2046
-        // grab event id
2047
-        if (! $EVT_ID) {
2048
-            $msg = esc_html__(
2049
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2050
-                'event_espresso'
2051
-            );
2052
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2053
-            return false;
2054
-        }
2055
-        $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2056
-        // clean status
2057
-        $event_status = sanitize_key($event_status);
2058
-        // grab status
2059
-        if (empty($event_status)) {
2060
-            $msg = esc_html__(
2061
-                'An error occurred. No Event Status or an invalid Event Status was received.',
2062
-                'event_espresso'
2063
-            );
2064
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2065
-            return false;
2066
-        }
2067
-        // was event trashed or restored ?
2068
-        switch ($event_status) {
2069
-            case 'draft':
2070
-                $action = 'restored from the trash';
2071
-                $hook = 'AHEE_event_restored_from_trash';
2072
-                break;
2073
-            case 'trash':
2074
-                $action = 'moved to the trash';
2075
-                $hook = 'AHEE_event_moved_to_trash';
2076
-                break;
2077
-            default:
2078
-                $action = 'updated';
2079
-                $hook = false;
2080
-        }
2081
-        // use class to change status
2082
-        $this->_cpt_model_obj->set_status($event_status);
2083
-        $success = $this->_cpt_model_obj->save();
2084
-        if ($success === false) {
2085
-            $msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2086
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2087
-            return false;
2088
-        }
2089
-        if ($hook) {
2090
-            do_action($hook);
2091
-        }
2092
-        return true;
2093
-    }
2094
-
2095
-
2096
-    /**
2097
-     * _delete_event
2098
-     *
2099
-     * @access protected
2100
-     * @param bool $redirect_after
2101
-     */
2102
-    protected function _delete_event()
2103
-    {
2104
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : array());
2105
-    }
2106
-
2107
-
2108
-    /**
2109
-     * _delete_events
2110
-     *
2111
-     * @access protected
2112
-     * @return void
2113
-     */
2114
-    protected function _delete_events()
2115
-    {
2116
-        $this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array());
2117
-    }
2118
-
2119
-    protected function generateDeletionPreview($event_ids)
2120
-    {
2121
-        $event_ids = (array) $event_ids;
2122
-        // Set a code we can use to reference this deletion task in the batch jobs and preview page.
2123
-        $deletion_job_code = wp_generate_password(6, false);
2124
-        $return_url = EE_Admin_Page::add_query_args_and_nonce(
2125
-            [
2126
-                'action' => 'preview_deletion',
2127
-                'deletion_job_code' => $deletion_job_code,
2128
-            ],
2129
-            $this->_admin_base_url
2130
-        );
2131
-        foreach ($event_ids as $EVT_ID) {
2132
-            $event_ids = (int) $EVT_ID;
2133
-        }
2134
-
2135
-        EEH_URL::safeRedirectAndExit(
2136
-            EE_Admin_Page::add_query_args_and_nonce(
2137
-                array(
2138
-                    'page'        => 'espresso_batch',
2139
-                    'batch'       => EED_Batch::batch_job,
2140
-                    'EVT_IDs[]'      => $event_ids,
2141
-                    'deletion_job_code' => $deletion_job_code,
2142
-                    'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2143
-                    'return_url'  => urlencode($return_url),
2144
-                ),
2145
-                admin_url()
2146
-            )
2147
-        );
2148
-    }
2149
-
2150
-    /**
2151
-     * Checks for a POST submission
2152
-     * @since $VID:$
2153
-     */
2154
-    protected function confirmDeletion()
2155
-    {
2156
-        $deletion_job_code = isset($this->_req_data['deletion_job_code']) ? $this->_req_data['deletion_job_code'] : '';
2157
-        $this->models_and_ids_to_delete = $this->getModelsAndIdsToDelete($deletion_job_code);
2158
-        $this->form = new ConfirmEventDeletionForm($this->models_and_ids_to_delete['Event']);
2159
-        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2160
-            // Initialize the form from the request, and check if its valid.
2161
-            $this->form->receive_form_submission($this->_req_data);
2162
-            if($this->form->is_valid()){
2163
-                // Redirect the user to the deletion batch job.
2164
-                EEH_URL::safeRedirectAndExit(
2165
-                    EE_Admin_Page::add_query_args_and_nonce(
2166
-                        array(
2167
-                            'page'        => 'espresso_batch',
2168
-                            'batch'       => EED_Batch::batch_job,
2169
-                            'deletion_job_code' => $deletion_job_code,
2170
-                            'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\ExecuteBatchDeletion'),
2171
-                            'return_url'  => urlencode(
2172
-                                add_query_arg(
2173
-                                    [
2174
-                                        'status' => 'trash'
2175
-                                    ],
2176
-                                    EVENTS_ADMIN_URL
2177
-                                )
2178
-                            )
2179
-                        ),
2180
-                        admin_url()
2181
-                    )
2182
-                );
2183
-            } else {
2184
-                EE_Error::add_error(
2185
-                    __(
2186
-                        'Data was not deleted because you did not complete the form correctly.',
2187
-                        'event_espresso'
2188
-                    ),
2189
-                    __FILE__,
2190
-                    __FUNCTION__,
2191
-                    __LINE__
2192
-                );
2193
-            }
2194
-        }
2195
-    }
2196
-
2197
-    /**
2198
-     * Uses the querystring and job option to figure out what we intend to delete.
2199
-     * @since $VID:$
2200
-     * @return array top-level keys are model names, and their values are arrays of IDs.
2201
-     * @throws EE_Error
2202
-     * @throws InvalidArgumentException
2203
-     * @throws InvalidDataTypeException
2204
-     * @throws InvalidInterfaceException
2205
-     * @throws ReflectionException
2206
-     * @throws UnexpectedEntityException
2207
-     */
2208
-    protected function getModelsAndIdsToDelete($deletion_job_code)
2209
-    {
2210
-        if( ! $deletion_job_code){
2211
-            throw new Exception(esc_html__('We aren’t sure which job you are performing. Please press back in your browser and try again.', 'event_espresso'));
2212
-        }
2213
-        $deletion_data = get_option('ee_deletion_' . $deletion_job_code, []);
2214
-
2215
-        $models_and_ids_to_delete = [];
2216
-        foreach ($deletion_data as $root) {
2217
-            if (! $root instanceof ModelObjNode) {
2218
-                throw new UnexpectedEntityException($root, 'ModelObjNode');
2219
-            }
2220
-            $models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
2221
-        }
2222
-        return $models_and_ids_to_delete;
2223
-    }
2224
-
2225
-    /**
2226
-     * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2227
-     * @since $VID:$
2228
-     */
2229
-    protected function previewDeletion()
2230
-    {
2231
-        $deletion_job_code = isset($this->_req_data['deletion_job_code']) ? $this->_req_data['deletion_job_code'] : '';
2232
-        if(! $this->form instanceof ConfirmEventDeletionForm){
2233
-            $this->models_and_ids_to_delete = $this->getModelsAndIdsToDelete($deletion_job_code);
2234
-            $this->form = new ConfirmEventDeletionForm($this->models_and_ids_to_delete['Event']);
2235
-        }
2236
-        // If they're not in debug mode, don't list all model objectss that will be deleted. They'll just be confused.
2237
-        if(! WP_DEBUG){
2238
-            $models_to_mention = [
2239
-                'Event',
2240
-                'Datetime',
2241
-                'Ticket',
2242
-                'Registration'
2243
-            ];
2244
-
2245
-            $this->models_and_ids_to_delete = array_intersect_key($this->models_and_ids_to_delete, array_flip($models_to_mention));
2246
-        };
2247
-        $confirm_deletion_args = [
2248
-            'action' => 'confirm_deletion',
2249
-            'deletion_job_code' => $deletion_job_code
2250
-        ];
2251
-
2252
-        $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2253
-            EVENTS_TEMPLATE_PATH . 'event_preview_deletion.template.php',
2254
-            [
2255
-                'form_url' => EE_Admin_Page::add_query_args_and_nonce(
2256
-                    $confirm_deletion_args,
2257
-                    $this->admin_base_url()
2258
-                ),
2259
-                'form' => $this->form,
2260
-                'models_and_ids_to_delete' => $this->models_and_ids_to_delete,
2261
-                'quantity_to_preview' => 20
2262
-            ],
2263
-            true
2264
-        );
2265
-        $this->display_admin_page_with_no_sidebar();
2266
-    }
2267
-
2268
-    /**
2269
-     * _permanently_delete_event
2270
-     *
2271
-     * @access  private
2272
-     * @param  int $EVT_ID
2273
-     * @return bool
2274
-     */
2275
-    private function _permanently_delete_event($EVT_ID = 0)
2276
-    {
2277
-        // grab event id
2278
-        if (! $EVT_ID) {
2279
-            $msg = esc_html__(
2280
-                'An error occurred. No Event ID or an invalid Event ID was received.',
2281
-                'event_espresso'
2282
-            );
2283
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2284
-            return false;
2285
-        }
2286
-        if (! $this->_cpt_model_obj instanceof EE_Event
2287
-            || $this->_cpt_model_obj->ID() !== $EVT_ID
2288
-        ) {
2289
-            $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2290
-        }
2291
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2292
-            return false;
2293
-        }
2294
-        // need to delete related tickets and prices first.
2295
-        $datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2296
-        foreach ($datetimes as $datetime) {
2297
-            $this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2298
-            $tickets = $datetime->get_many_related('Ticket');
2299
-            foreach ($tickets as $ticket) {
2300
-                $ticket->_remove_relation_to($datetime, 'Datetime');
2301
-                $ticket->delete_related_permanently('Price');
2302
-                $ticket->delete_permanently();
2303
-            }
2304
-            $datetime->delete();
2305
-        }
2306
-        // what about related venues or terms?
2307
-        $venues = $this->_cpt_model_obj->get_many_related('Venue');
2308
-        foreach ($venues as $venue) {
2309
-            $this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2310
-        }
2311
-        // any attached question groups?
2312
-        $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2313
-        if (! empty($question_groups)) {
2314
-            foreach ($question_groups as $question_group) {
2315
-                $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2316
-            }
2317
-        }
2318
-        // Message Template Groups
2319
-        $this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2320
-        /** @type EE_Term_Taxonomy[] $term_taxonomies */
2321
-        $term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2322
-        foreach ($term_taxonomies as $term_taxonomy) {
2323
-            $this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2324
-        }
2325
-        $success = $this->_cpt_model_obj->delete_permanently();
2326
-        // did it all go as planned ?
2327
-        if ($success) {
2328
-            $msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2329
-            EE_Error::add_success($msg);
2330
-        } else {
2331
-            $msg = sprintf(
2332
-                esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2333
-                $EVT_ID
2334
-            );
2335
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2336
-            return false;
2337
-        }
2338
-        do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2339
-        return true;
2340
-    }
2341
-
2342
-
2343
-    /**
2344
-     * get total number of events
2345
-     *
2346
-     * @access public
2347
-     * @return int
2348
-     */
2349
-    public function total_events()
2350
-    {
2351
-        $count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2352
-        return $count;
2353
-    }
2354
-
2355
-
2356
-    /**
2357
-     * get total number of draft events
2358
-     *
2359
-     * @access public
2360
-     * @return int
2361
-     */
2362
-    public function total_events_draft()
2363
-    {
2364
-        $where = array(
2365
-            'status' => array('IN', array('draft', 'auto-draft')),
2366
-        );
2367
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2368
-        return $count;
2369
-    }
2370
-
2371
-
2372
-    /**
2373
-     * get total number of trashed events
2374
-     *
2375
-     * @access public
2376
-     * @return int
2377
-     */
2378
-    public function total_trashed_events()
2379
-    {
2380
-        $where = array(
2381
-            'status' => 'trash',
2382
-        );
2383
-        $count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2384
-        return $count;
2385
-    }
2386
-
2387
-
2388
-    /**
2389
-     *    _default_event_settings
2390
-     *    This generates the Default Settings Tab
2391
-     *
2392
-     * @return void
2393
-     * @throws EE_Error
2394
-     */
2395
-    protected function _default_event_settings()
2396
-    {
2397
-        $this->_set_add_edit_form_tags('update_default_event_settings');
2398
-        $this->_set_publish_post_box_vars(null, false, false, null, false);
2399
-        $this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2400
-        $this->display_admin_page_with_sidebar();
2401
-    }
2402
-
2403
-
2404
-    /**
2405
-     * Return the form for event settings.
2406
-     *
2407
-     * @return EE_Form_Section_Proper
2408
-     * @throws EE_Error
2409
-     */
2410
-    protected function _default_event_settings_form()
2411
-    {
2412
-        $registration_config = EE_Registry::instance()->CFG->registration;
2413
-        $registration_stati_for_selection = EEM_Registration::reg_status_array(
2414
-            // exclude
2415
-            array(
2416
-                EEM_Registration::status_id_cancelled,
2417
-                EEM_Registration::status_id_declined,
2418
-                EEM_Registration::status_id_incomplete,
2419
-                EEM_Registration::status_id_wait_list,
2420
-            ),
2421
-            true
2422
-        );
2423
-        return new EE_Form_Section_Proper(
2424
-            array(
2425
-                'name'            => 'update_default_event_settings',
2426
-                'html_id'         => 'update_default_event_settings',
2427
-                'html_class'      => 'form-table',
2428
-                'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2429
-                'subsections'     => apply_filters(
2430
-                    'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2431
-                    array(
2432
-                        'default_reg_status'  => new EE_Select_Input(
2433
-                            $registration_stati_for_selection,
2434
-                            array(
2435
-                                'default'         => isset($registration_config->default_STS_ID)
2436
-                                                     && array_key_exists(
2437
-                                                         $registration_config->default_STS_ID,
2438
-                                                         $registration_stati_for_selection
2439
-                                                     )
2440
-                                    ? sanitize_text_field($registration_config->default_STS_ID)
2441
-                                    : EEM_Registration::status_id_pending_payment,
2442
-                                'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2443
-                                                     . EEH_Template::get_help_tab_link(
2444
-                                                         'default_settings_status_help_tab'
2445
-                                                     ),
2446
-                                'html_help_text'  => esc_html__(
2447
-                                    'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2448
-                                    'event_espresso'
2449
-                                ),
2450
-                            )
2451
-                        ),
2452
-                        'default_max_tickets' => new EE_Integer_Input(
2453
-                            array(
2454
-                                'default'         => isset($registration_config->default_maximum_number_of_tickets)
2455
-                                    ? $registration_config->default_maximum_number_of_tickets
2456
-                                    : EEM_Event::get_default_additional_limit(),
2457
-                                'html_label_text' => esc_html__(
2458
-                                    'Default Maximum Tickets Allowed Per Order:',
2459
-                                    'event_espresso'
2460
-                                )
2461
-                                                     . EEH_Template::get_help_tab_link(
2462
-                                                         'default_maximum_tickets_help_tab"'
2463
-                                                     ),
2464
-                                'html_help_text'  => esc_html__(
2465
-                                    'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2466
-                                    'event_espresso'
2467
-                                ),
2468
-                            )
2469
-                        ),
2470
-                    )
2471
-                ),
2472
-            )
2473
-        );
2474
-    }
2475
-
2476
-
2477
-    /**
2478
-     * _update_default_event_settings
2479
-     *
2480
-     * @access protected
2481
-     * @return void
2482
-     * @throws EE_Error
2483
-     */
2484
-    protected function _update_default_event_settings()
2485
-    {
2486
-        $registration_config = EE_Registry::instance()->CFG->registration;
2487
-        $form = $this->_default_event_settings_form();
2488
-        if ($form->was_submitted()) {
2489
-            $form->receive_form_submission();
2490
-            if ($form->is_valid()) {
2491
-                $valid_data = $form->valid_data();
2492
-                if (isset($valid_data['default_reg_status'])) {
2493
-                    $registration_config->default_STS_ID = $valid_data['default_reg_status'];
2494
-                }
2495
-                if (isset($valid_data['default_max_tickets'])) {
2496
-                    $registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2497
-                }
2498
-                // update because data was valid!
2499
-                EE_Registry::instance()->CFG->update_espresso_config();
2500
-                EE_Error::overwrite_success();
2501
-                EE_Error::add_success(
2502
-                    __('Default Event Settings were updated', 'event_espresso')
2503
-                );
2504
-            }
2505
-        }
2506
-        $this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2507
-    }
2508
-
2509
-
2510
-    /*************        Templates        *************/
2511
-    protected function _template_settings()
2512
-    {
2513
-        $this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2514
-        $this->_template_args['preview_img'] = '<img src="'
2515
-                                               . EVENTS_ASSETS_URL
2516
-                                               . '/images/'
2517
-                                               . 'caffeinated_template_features.jpg" alt="'
2518
-                                               . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2519
-                                               . '" />';
2520
-        $this->_template_args['preview_text'] = '<strong>'
2521
-                                                . esc_html__(
2522
-                                                    'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2523
-                                                    'event_espresso'
2524
-                                                ) . '</strong>';
2525
-        $this->display_admin_caf_preview_page('template_settings_tab');
2526
-    }
2527
-
2528
-
2529
-    /** Event Category Stuff **/
2530
-    /**
2531
-     * set the _category property with the category object for the loaded page.
2532
-     *
2533
-     * @access private
2534
-     * @return void
2535
-     */
2536
-    private function _set_category_object()
2537
-    {
2538
-        if (isset($this->_category->id) && ! empty($this->_category->id)) {
2539
-            return;
2540
-        } //already have the category object so get out.
2541
-        // set default category object
2542
-        $this->_set_empty_category_object();
2543
-        // only set if we've got an id
2544
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2545
-            return;
2546
-        }
2547
-        $category_id = absint($this->_req_data['EVT_CAT_ID']);
2548
-        $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2549
-        if (! empty($term)) {
2550
-            $this->_category->category_name = $term->name;
2551
-            $this->_category->category_identifier = $term->slug;
2552
-            $this->_category->category_desc = $term->description;
2553
-            $this->_category->id = $term->term_id;
2554
-            $this->_category->parent = $term->parent;
2555
-        }
2556
-    }
2557
-
2558
-
2559
-    /**
2560
-     * Clears out category properties.
2561
-     */
2562
-    private function _set_empty_category_object()
2563
-    {
2564
-        $this->_category = new stdClass();
2565
-        $this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2566
-        $this->_category->id = $this->_category->parent = 0;
2567
-    }
2568
-
2569
-
2570
-    /**
2571
-     * @throws EE_Error
2572
-     */
2573
-    protected function _category_list_table()
2574
-    {
2575
-        do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2576
-        $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2577
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2578
-            'add_category',
2579
-            'add_category',
2580
-            array(),
2581
-            'add-new-h2'
2582
-        );
2583
-        $this->display_admin_list_table_page_with_sidebar();
2584
-    }
2585
-
2586
-
2587
-    /**
2588
-     * Output category details view.
2589
-     */
2590
-    protected function _category_details($view)
2591
-    {
2592
-        // load formatter helper
2593
-        // load field generator helper
2594
-        $route = $view == 'edit' ? 'update_category' : 'insert_category';
2595
-        $this->_set_add_edit_form_tags($route);
2596
-        $this->_set_category_object();
2597
-        $id = ! empty($this->_category->id) ? $this->_category->id : '';
2598
-        $delete_action = 'delete_category';
2599
-        // custom redirect
2600
-        $redirect = EE_Admin_Page::add_query_args_and_nonce(
2601
-            array('action' => 'category_list'),
2602
-            $this->_admin_base_url
2603
-        );
2604
-        $this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2605
-        // take care of contents
2606
-        $this->_template_args['admin_page_content'] = $this->_category_details_content();
2607
-        $this->display_admin_page_with_sidebar();
2608
-    }
2609
-
2610
-
2611
-    /**
2612
-     * Output category details content.
2613
-     */
2614
-    protected function _category_details_content()
2615
-    {
2616
-        $editor_args['category_desc'] = array(
2617
-            'type'          => 'wp_editor',
2618
-            'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2619
-            'class'         => 'my_editor_custom',
2620
-            'wpeditor_args' => array('media_buttons' => false),
2621
-        );
2622
-        $_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2623
-        $all_terms = get_terms(
2624
-            array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2625
-            array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2626
-        );
2627
-        // setup category select for term parents.
2628
-        $category_select_values[] = array(
2629
-            'text' => esc_html__('No Parent', 'event_espresso'),
2630
-            'id'   => 0,
2631
-        );
2632
-        foreach ($all_terms as $term) {
2633
-            $category_select_values[] = array(
2634
-                'text' => $term->name,
2635
-                'id'   => $term->term_id,
2636
-            );
2637
-        }
2638
-        $category_select = EEH_Form_Fields::select_input(
2639
-            'category_parent',
2640
-            $category_select_values,
2641
-            $this->_category->parent
2642
-        );
2643
-        $template_args = array(
2644
-            'category'                 => $this->_category,
2645
-            'category_select'          => $category_select,
2646
-            'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2647
-            'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2648
-            'disable'                  => '',
2649
-            'disabled_message'         => false,
2650
-        );
2651
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2652
-        return EEH_Template::display_template($template, $template_args, true);
2653
-    }
2654
-
2655
-
2656
-    /**
2657
-     * Handles deleting categories.
2658
-     */
2659
-    protected function _delete_categories()
2660
-    {
2661
-        $cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2662
-            : (array) $this->_req_data['category_id'];
2663
-        foreach ($cat_ids as $cat_id) {
2664
-            $this->_delete_category($cat_id);
2665
-        }
2666
-        // doesn't matter what page we're coming from... we're going to the same place after delete.
2667
-        $query_args = array(
2668
-            'action' => 'category_list',
2669
-        );
2670
-        $this->_redirect_after_action(0, '', '', $query_args);
2671
-    }
2672
-
2673
-
2674
-    /**
2675
-     * Handles deleting specific category.
2676
-     *
2677
-     * @param int $cat_id
2678
-     */
2679
-    protected function _delete_category($cat_id)
2680
-    {
2681
-        $cat_id = absint($cat_id);
2682
-        wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2683
-    }
2684
-
2685
-
2686
-    /**
2687
-     * Handles triggering the update or insertion of a new category.
2688
-     *
2689
-     * @param bool $new_category true means we're triggering the insert of a new category.
2690
-     */
2691
-    protected function _insert_or_update_category($new_category)
2692
-    {
2693
-        $cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2694
-        $success = 0; // we already have a success message so lets not send another.
2695
-        if ($cat_id) {
2696
-            $query_args = array(
2697
-                'action'     => 'edit_category',
2698
-                'EVT_CAT_ID' => $cat_id,
2699
-            );
2700
-        } else {
2701
-            $query_args = array('action' => 'add_category');
2702
-        }
2703
-        $this->_redirect_after_action($success, '', '', $query_args, true);
2704
-    }
2705
-
2706
-
2707
-    /**
2708
-     * Inserts or updates category
2709
-     *
2710
-     * @param bool $update (true indicates we're updating a category).
2711
-     * @return bool|mixed|string
2712
-     */
2713
-    private function _insert_category($update = false)
2714
-    {
2715
-        $cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2716
-        $category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2717
-        $category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2718
-        $category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2719
-        if (empty($category_name)) {
2720
-            $msg = esc_html__('You must add a name for the category.', 'event_espresso');
2721
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2722
-            return false;
2723
-        }
2724
-        $term_args = array(
2725
-            'name'        => $category_name,
2726
-            'description' => $category_desc,
2727
-            'parent'      => $category_parent,
2728
-        );
2729
-        // was the category_identifier input disabled?
2730
-        if (isset($this->_req_data['category_identifier'])) {
2731
-            $term_args['slug'] = $this->_req_data['category_identifier'];
2732
-        }
2733
-        $insert_ids = $update
2734
-            ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2735
-            : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2736
-        if (! is_array($insert_ids)) {
2737
-            $msg = esc_html__(
2738
-                'An error occurred and the category has not been saved to the database.',
2739
-                'event_espresso'
2740
-            );
2741
-            EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2742
-        } else {
2743
-            $cat_id = $insert_ids['term_id'];
2744
-            $msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2745
-            EE_Error::add_success($msg);
2746
-        }
2747
-        return $cat_id;
2748
-    }
2749
-
2750
-
2751
-    /**
2752
-     * Gets categories or count of categories matching the arguments in the request.
2753
-     *
2754
-     * @param int  $per_page
2755
-     * @param int  $current_page
2756
-     * @param bool $count
2757
-     * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2758
-     */
2759
-    public function get_categories($per_page = 10, $current_page = 1, $count = false)
2760
-    {
2761
-        // testing term stuff
2762
-        $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2763
-        $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2764
-        $limit = ($current_page - 1) * $per_page;
2765
-        $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2766
-        if (isset($this->_req_data['s'])) {
2767
-            $sstr = '%' . $this->_req_data['s'] . '%';
2768
-            $where['OR'] = array(
2769
-                'Term.name'   => array('LIKE', $sstr),
2770
-                'description' => array('LIKE', $sstr),
2771
-            );
2772
-        }
2773
-        $query_params = array(
2774
-            $where,
2775
-            'order_by'   => array($orderby => $order),
2776
-            'limit'      => $limit . ',' . $per_page,
2777
-            'force_join' => array('Term'),
2778
-        );
2779
-        $categories = $count
2780
-            ? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2781
-            : EEM_Term_Taxonomy::instance()->get_all($query_params);
2782
-        return $categories;
2783
-    }
2784
-
2785
-    /* end category stuff */
2786
-    /**************/
2787
-
2788
-
2789
-    /**
2790
-     * Callback for the `ee_save_timezone_setting` ajax action.
2791
-     *
2792
-     * @throws EE_Error
2793
-     */
2794
-    public function save_timezonestring_setting()
2795
-    {
2796
-        $timezone_string = isset($this->_req_data['timezone_selected'])
2797
-            ? $this->_req_data['timezone_selected']
2798
-            : '';
2799
-        if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2800
-            EE_Error::add_error(
2801
-                esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2802
-                __FILE__,
2803
-                __FUNCTION__,
2804
-                __LINE__
2805
-            );
2806
-            $this->_template_args['error'] = true;
2807
-            $this->_return_json();
2808
-        }
2809
-
2810
-        update_option('timezone_string', $timezone_string);
2811
-        EE_Error::add_success(
2812
-            esc_html__('Your timezone string was updated.', 'event_espresso')
2813
-        );
2814
-        $this->_template_args['success'] = true;
2815
-        $this->_return_json(true, array('action' => 'create_new'));
2816
-    }
21
+	/**
22
+	 * This will hold the event object for event_details screen.
23
+	 *
24
+	 * @access protected
25
+	 * @var EE_Event $_event
26
+	 */
27
+	protected $_event;
28
+
29
+
30
+	/**
31
+	 * This will hold the category object for category_details screen.
32
+	 *
33
+	 * @var stdClass $_category
34
+	 */
35
+	protected $_category;
36
+
37
+
38
+	/**
39
+	 * This will hold the event model instance
40
+	 *
41
+	 * @var EEM_Event $_event_model
42
+	 */
43
+	protected $_event_model;
44
+
45
+
46
+	/**
47
+	 * @var EE_Event
48
+	 */
49
+	protected $_cpt_model_obj = false;
50
+
51
+	/**
52
+	 * Used to hold onto a form across various stages of a request.
53
+	 * @var EE_Form_Section_Proper
54
+	 */
55
+	protected $form;
56
+
57
+	/**
58
+	 * Used so we don't have to repeatedly fetch a potentially large array of data from the WP options table.
59
+	 * @var array
60
+	 */
61
+	protected $models_and_ids_to_delete;
62
+
63
+
64
+	/**
65
+	 * Initialize page props for this admin page group.
66
+	 */
67
+	protected function _init_page_props()
68
+	{
69
+		$this->page_slug = EVENTS_PG_SLUG;
70
+		$this->page_label = EVENTS_LABEL;
71
+		$this->_admin_base_url = EVENTS_ADMIN_URL;
72
+		$this->_admin_base_path = EVENTS_ADMIN;
73
+		$this->_cpt_model_names = array(
74
+			'create_new' => 'EEM_Event',
75
+			'edit'       => 'EEM_Event',
76
+		);
77
+		$this->_cpt_edit_routes = array(
78
+			'espresso_events' => 'edit',
79
+		);
80
+		add_action(
81
+			'AHEE__EE_Admin_Page_CPT__set_model_object__after_set_object',
82
+			array($this, 'verify_event_edit'),
83
+			10,
84
+			2
85
+		);
86
+	}
87
+
88
+
89
+	/**
90
+	 * Sets the ajax hooks used for this admin page group.
91
+	 */
92
+	protected function _ajax_hooks()
93
+	{
94
+		add_action('wp_ajax_ee_save_timezone_setting', array($this, 'save_timezonestring_setting'));
95
+	}
96
+
97
+
98
+	/**
99
+	 * Sets the page properties for this admin page group.
100
+	 */
101
+	protected function _define_page_props()
102
+	{
103
+		$this->_admin_page_title = EVENTS_LABEL;
104
+		$this->_labels = array(
105
+			'buttons'      => array(
106
+				'add'             => esc_html__('Add New Event', 'event_espresso'),
107
+				'edit'            => esc_html__('Edit Event', 'event_espresso'),
108
+				'delete'          => esc_html__('Delete Event', 'event_espresso'),
109
+				'add_category'    => esc_html__('Add New Category', 'event_espresso'),
110
+				'edit_category'   => esc_html__('Edit Category', 'event_espresso'),
111
+				'delete_category' => esc_html__('Delete Category', 'event_espresso'),
112
+			),
113
+			'editor_title' => array(
114
+				'espresso_events' => esc_html__('Enter event title here', 'event_espresso'),
115
+			),
116
+			'publishbox'   => array(
117
+				'create_new'        => esc_html__('Save New Event', 'event_espresso'),
118
+				'edit'              => esc_html__('Update Event', 'event_espresso'),
119
+				'add_category'      => esc_html__('Save New Category', 'event_espresso'),
120
+				'edit_category'     => esc_html__('Update Category', 'event_espresso'),
121
+				'template_settings' => esc_html__('Update Settings', 'event_espresso'),
122
+			),
123
+		);
124
+	}
125
+
126
+
127
+	/**
128
+	 * Sets the page routes property for this admin page group.
129
+	 */
130
+	protected function _set_page_routes()
131
+	{
132
+		// load formatter helper
133
+		// load field generator helper
134
+		// is there a evt_id in the request?
135
+		$evt_id = ! empty($this->_req_data['EVT_ID']) && ! is_array($this->_req_data['EVT_ID'])
136
+			? $this->_req_data['EVT_ID']
137
+			: 0;
138
+		$evt_id = ! empty($this->_req_data['post']) ? $this->_req_data['post'] : $evt_id;
139
+		$this->_page_routes = array(
140
+			'default'                       => array(
141
+				'func'       => '_events_overview_list_table',
142
+				'capability' => 'ee_read_events',
143
+			),
144
+			'create_new'                    => array(
145
+				'func'       => '_create_new_cpt_item',
146
+				'capability' => 'ee_edit_events',
147
+			),
148
+			'edit'                          => array(
149
+				'func'       => '_edit_cpt_item',
150
+				'capability' => 'ee_edit_event',
151
+				'obj_id'     => $evt_id,
152
+			),
153
+			'copy_event'                    => array(
154
+				'func'       => '_copy_events',
155
+				'capability' => 'ee_edit_event',
156
+				'obj_id'     => $evt_id,
157
+				'noheader'   => true,
158
+			),
159
+			'trash_event'                   => array(
160
+				'func'       => '_trash_or_restore_event',
161
+				'args'       => array('event_status' => 'trash'),
162
+				'capability' => 'ee_delete_event',
163
+				'obj_id'     => $evt_id,
164
+				'noheader'   => true,
165
+			),
166
+			'trash_events'                  => array(
167
+				'func'       => '_trash_or_restore_events',
168
+				'args'       => array('event_status' => 'trash'),
169
+				'capability' => 'ee_delete_events',
170
+				'noheader'   => true,
171
+			),
172
+			'restore_event'                 => array(
173
+				'func'       => '_trash_or_restore_event',
174
+				'args'       => array('event_status' => 'draft'),
175
+				'capability' => 'ee_delete_event',
176
+				'obj_id'     => $evt_id,
177
+				'noheader'   => true,
178
+			),
179
+			'restore_events'                => array(
180
+				'func'       => '_trash_or_restore_events',
181
+				'args'       => array('event_status' => 'draft'),
182
+				'capability' => 'ee_delete_events',
183
+				'noheader'   => true,
184
+			),
185
+			'delete_event'                  => array(
186
+				'func'       => '_delete_event',
187
+				'capability' => 'ee_delete_event',
188
+				'obj_id'     => $evt_id,
189
+				'noheader'   => true,
190
+			),
191
+			'delete_events'                 => array(
192
+				'func'       => '_delete_events',
193
+				'capability' => 'ee_delete_events',
194
+				'noheader'   => true,
195
+			),
196
+			'view_report'                   => array(
197
+				'func'      => '_view_report',
198
+				'capablity' => 'ee_edit_events',
199
+			),
200
+			'default_event_settings'        => array(
201
+				'func'       => '_default_event_settings',
202
+				'capability' => 'manage_options',
203
+			),
204
+			'update_default_event_settings' => array(
205
+				'func'       => '_update_default_event_settings',
206
+				'capability' => 'manage_options',
207
+				'noheader'   => true,
208
+			),
209
+			'template_settings'             => array(
210
+				'func'       => '_template_settings',
211
+				'capability' => 'manage_options',
212
+			),
213
+			// event category tab related
214
+			'add_category'                  => array(
215
+				'func'       => '_category_details',
216
+				'capability' => 'ee_edit_event_category',
217
+				'args'       => array('add'),
218
+			),
219
+			'edit_category'                 => array(
220
+				'func'       => '_category_details',
221
+				'capability' => 'ee_edit_event_category',
222
+				'args'       => array('edit'),
223
+			),
224
+			'delete_categories'             => array(
225
+				'func'       => '_delete_categories',
226
+				'capability' => 'ee_delete_event_category',
227
+				'noheader'   => true,
228
+			),
229
+			'delete_category'               => array(
230
+				'func'       => '_delete_categories',
231
+				'capability' => 'ee_delete_event_category',
232
+				'noheader'   => true,
233
+			),
234
+			'insert_category'               => array(
235
+				'func'       => '_insert_or_update_category',
236
+				'args'       => array('new_category' => true),
237
+				'capability' => 'ee_edit_event_category',
238
+				'noheader'   => true,
239
+			),
240
+			'update_category'               => array(
241
+				'func'       => '_insert_or_update_category',
242
+				'args'       => array('new_category' => false),
243
+				'capability' => 'ee_edit_event_category',
244
+				'noheader'   => true,
245
+			),
246
+			'category_list'                 => array(
247
+				'func'       => '_category_list_table',
248
+				'capability' => 'ee_manage_event_categories',
249
+			),
250
+			'preview_deletion' => [
251
+				'func' => 'previewDeletion',
252
+				'capability' => 'ee_delete_events',
253
+			],
254
+			'confirm_deletion' => [
255
+				'func' => 'confirmDeletion',
256
+				'capability' => 'ee_delete_events',
257
+				'noheader' => true,
258
+				'headers_sent_route' => 'preview_deletion',
259
+			]
260
+		);
261
+	}
262
+
263
+
264
+	/**
265
+	 * Set the _page_config property for this admin page group.
266
+	 */
267
+	protected function _set_page_config()
268
+	{
269
+		$this->_page_config = array(
270
+			'default'                => array(
271
+				'nav'           => array(
272
+					'label' => esc_html__('Overview', 'event_espresso'),
273
+					'order' => 10,
274
+				),
275
+				'list_table'    => 'Events_Admin_List_Table',
276
+				'help_tabs'     => array(
277
+					'events_overview_help_tab'                       => array(
278
+						'title'    => esc_html__('Events Overview', 'event_espresso'),
279
+						'filename' => 'events_overview',
280
+					),
281
+					'events_overview_table_column_headings_help_tab' => array(
282
+						'title'    => esc_html__('Events Overview Table Column Headings', 'event_espresso'),
283
+						'filename' => 'events_overview_table_column_headings',
284
+					),
285
+					'events_overview_filters_help_tab'               => array(
286
+						'title'    => esc_html__('Events Overview Filters', 'event_espresso'),
287
+						'filename' => 'events_overview_filters',
288
+					),
289
+					'events_overview_view_help_tab'                  => array(
290
+						'title'    => esc_html__('Events Overview Views', 'event_espresso'),
291
+						'filename' => 'events_overview_views',
292
+					),
293
+					'events_overview_other_help_tab'                 => array(
294
+						'title'    => esc_html__('Events Overview Other', 'event_espresso'),
295
+						'filename' => 'events_overview_other',
296
+					),
297
+				),
298
+				'help_tour'     => array(
299
+					'Event_Overview_Help_Tour',
300
+					// 'New_Features_Test_Help_Tour' for testing multiple help tour
301
+				),
302
+				'qtips'         => array(
303
+					'EE_Event_List_Table_Tips',
304
+				),
305
+				'require_nonce' => false,
306
+			),
307
+			'create_new'             => array(
308
+				'nav'           => array(
309
+					'label'      => esc_html__('Add Event', 'event_espresso'),
310
+					'order'      => 5,
311
+					'persistent' => false,
312
+				),
313
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
314
+				'help_tabs'     => array(
315
+					'event_editor_help_tab'                            => array(
316
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
317
+						'filename' => 'event_editor',
318
+					),
319
+					'event_editor_title_richtexteditor_help_tab'       => array(
320
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
321
+						'filename' => 'event_editor_title_richtexteditor',
322
+					),
323
+					'event_editor_venue_details_help_tab'              => array(
324
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
325
+						'filename' => 'event_editor_venue_details',
326
+					),
327
+					'event_editor_event_datetimes_help_tab'            => array(
328
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
329
+						'filename' => 'event_editor_event_datetimes',
330
+					),
331
+					'event_editor_event_tickets_help_tab'              => array(
332
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
333
+						'filename' => 'event_editor_event_tickets',
334
+					),
335
+					'event_editor_event_registration_options_help_tab' => array(
336
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
337
+						'filename' => 'event_editor_event_registration_options',
338
+					),
339
+					'event_editor_tags_categories_help_tab'            => array(
340
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
341
+						'filename' => 'event_editor_tags_categories',
342
+					),
343
+					'event_editor_questions_registrants_help_tab'      => array(
344
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
345
+						'filename' => 'event_editor_questions_registrants',
346
+					),
347
+					'event_editor_save_new_event_help_tab'             => array(
348
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
349
+						'filename' => 'event_editor_save_new_event',
350
+					),
351
+					'event_editor_other_help_tab'                      => array(
352
+						'title'    => esc_html__('Event Other', 'event_espresso'),
353
+						'filename' => 'event_editor_other',
354
+					),
355
+				),
356
+				'help_tour'     => array(
357
+					'Event_Editor_Help_Tour',
358
+				),
359
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
360
+				'require_nonce' => false,
361
+			),
362
+			'edit'                   => array(
363
+				'nav'           => array(
364
+					'label'      => esc_html__('Edit Event', 'event_espresso'),
365
+					'order'      => 5,
366
+					'persistent' => false,
367
+					'url'        => isset($this->_req_data['post'])
368
+						? EE_Admin_Page::add_query_args_and_nonce(
369
+							array('post' => $this->_req_data['post'], 'action' => 'edit'),
370
+							$this->_current_page_view_url
371
+						)
372
+						: $this->_admin_base_url,
373
+				),
374
+				'metaboxes'     => array('_register_event_editor_meta_boxes'),
375
+				'help_tabs'     => array(
376
+					'event_editor_help_tab'                            => array(
377
+						'title'    => esc_html__('Event Editor', 'event_espresso'),
378
+						'filename' => 'event_editor',
379
+					),
380
+					'event_editor_title_richtexteditor_help_tab'       => array(
381
+						'title'    => esc_html__('Event Title & Rich Text Editor', 'event_espresso'),
382
+						'filename' => 'event_editor_title_richtexteditor',
383
+					),
384
+					'event_editor_venue_details_help_tab'              => array(
385
+						'title'    => esc_html__('Event Venue Details', 'event_espresso'),
386
+						'filename' => 'event_editor_venue_details',
387
+					),
388
+					'event_editor_event_datetimes_help_tab'            => array(
389
+						'title'    => esc_html__('Event Datetimes', 'event_espresso'),
390
+						'filename' => 'event_editor_event_datetimes',
391
+					),
392
+					'event_editor_event_tickets_help_tab'              => array(
393
+						'title'    => esc_html__('Event Tickets', 'event_espresso'),
394
+						'filename' => 'event_editor_event_tickets',
395
+					),
396
+					'event_editor_event_registration_options_help_tab' => array(
397
+						'title'    => esc_html__('Event Registration Options', 'event_espresso'),
398
+						'filename' => 'event_editor_event_registration_options',
399
+					),
400
+					'event_editor_tags_categories_help_tab'            => array(
401
+						'title'    => esc_html__('Event Tags & Categories', 'event_espresso'),
402
+						'filename' => 'event_editor_tags_categories',
403
+					),
404
+					'event_editor_questions_registrants_help_tab'      => array(
405
+						'title'    => esc_html__('Questions for Registrants', 'event_espresso'),
406
+						'filename' => 'event_editor_questions_registrants',
407
+					),
408
+					'event_editor_save_new_event_help_tab'             => array(
409
+						'title'    => esc_html__('Save New Event', 'event_espresso'),
410
+						'filename' => 'event_editor_save_new_event',
411
+					),
412
+					'event_editor_other_help_tab'                      => array(
413
+						'title'    => esc_html__('Event Other', 'event_espresso'),
414
+						'filename' => 'event_editor_other',
415
+					),
416
+				),
417
+				'qtips'         => array('EE_Event_Editor_Decaf_Tips'),
418
+				'require_nonce' => false,
419
+			),
420
+			'default_event_settings' => array(
421
+				'nav'           => array(
422
+					'label' => esc_html__('Default Settings', 'event_espresso'),
423
+					'order' => 40,
424
+				),
425
+				'metaboxes'     => array_merge($this->_default_espresso_metaboxes, array('_publish_post_box')),
426
+				'labels'        => array(
427
+					'publishbox' => esc_html__('Update Settings', 'event_espresso'),
428
+				),
429
+				'help_tabs'     => array(
430
+					'default_settings_help_tab'        => array(
431
+						'title'    => esc_html__('Default Event Settings', 'event_espresso'),
432
+						'filename' => 'events_default_settings',
433
+					),
434
+					'default_settings_status_help_tab' => array(
435
+						'title'    => esc_html__('Default Registration Status', 'event_espresso'),
436
+						'filename' => 'events_default_settings_status',
437
+					),
438
+					'default_maximum_tickets_help_tab' => array(
439
+						'title'    => esc_html__('Default Maximum Tickets Per Order', 'event_espresso'),
440
+						'filename' => 'events_default_settings_max_tickets',
441
+					),
442
+				),
443
+				'help_tour'     => array('Event_Default_Settings_Help_Tour'),
444
+				'require_nonce' => false,
445
+			),
446
+			// template settings
447
+			'template_settings'      => array(
448
+				'nav'           => array(
449
+					'label' => esc_html__('Templates', 'event_espresso'),
450
+					'order' => 30,
451
+				),
452
+				'metaboxes'     => $this->_default_espresso_metaboxes,
453
+				'help_tabs'     => array(
454
+					'general_settings_templates_help_tab' => array(
455
+						'title'    => esc_html__('Templates', 'event_espresso'),
456
+						'filename' => 'general_settings_templates',
457
+					),
458
+				),
459
+				'help_tour'     => array('Templates_Help_Tour'),
460
+				'require_nonce' => false,
461
+			),
462
+			// event category stuff
463
+			'add_category'           => array(
464
+				'nav'           => array(
465
+					'label'      => esc_html__('Add Category', 'event_espresso'),
466
+					'order'      => 15,
467
+					'persistent' => false,
468
+				),
469
+				'help_tabs'     => array(
470
+					'add_category_help_tab' => array(
471
+						'title'    => esc_html__('Add New Event Category', 'event_espresso'),
472
+						'filename' => 'events_add_category',
473
+					),
474
+				),
475
+				'help_tour'     => array('Event_Add_Category_Help_Tour'),
476
+				'metaboxes'     => array('_publish_post_box'),
477
+				'require_nonce' => false,
478
+			),
479
+			'edit_category'          => array(
480
+				'nav'           => array(
481
+					'label'      => esc_html__('Edit Category', 'event_espresso'),
482
+					'order'      => 15,
483
+					'persistent' => false,
484
+					'url'        => isset($this->_req_data['EVT_CAT_ID'])
485
+						? add_query_arg(
486
+							array('EVT_CAT_ID' => $this->_req_data['EVT_CAT_ID']),
487
+							$this->_current_page_view_url
488
+						)
489
+						: $this->_admin_base_url,
490
+				),
491
+				'help_tabs'     => array(
492
+					'edit_category_help_tab' => array(
493
+						'title'    => esc_html__('Edit Event Category', 'event_espresso'),
494
+						'filename' => 'events_edit_category',
495
+					),
496
+				),
497
+				/*'help_tour' => array('Event_Edit_Category_Help_Tour'),*/
498
+				'metaboxes'     => array('_publish_post_box'),
499
+				'require_nonce' => false,
500
+			),
501
+			'category_list'          => array(
502
+				'nav'           => array(
503
+					'label' => esc_html__('Categories', 'event_espresso'),
504
+					'order' => 20,
505
+				),
506
+				'list_table'    => 'Event_Categories_Admin_List_Table',
507
+				'help_tabs'     => array(
508
+					'events_categories_help_tab'                       => array(
509
+						'title'    => esc_html__('Event Categories', 'event_espresso'),
510
+						'filename' => 'events_categories',
511
+					),
512
+					'events_categories_table_column_headings_help_tab' => array(
513
+						'title'    => esc_html__('Event Categories Table Column Headings', 'event_espresso'),
514
+						'filename' => 'events_categories_table_column_headings',
515
+					),
516
+					'events_categories_view_help_tab'                  => array(
517
+						'title'    => esc_html__('Event Categories Views', 'event_espresso'),
518
+						'filename' => 'events_categories_views',
519
+					),
520
+					'events_categories_other_help_tab'                 => array(
521
+						'title'    => esc_html__('Event Categories Other', 'event_espresso'),
522
+						'filename' => 'events_categories_other',
523
+					),
524
+				),
525
+				'help_tour'     => array(
526
+					'Event_Categories_Help_Tour',
527
+				),
528
+				'metaboxes'     => $this->_default_espresso_metaboxes,
529
+				'require_nonce' => false,
530
+			),
531
+			'preview_deletion'           => array(
532
+				'nav'           => array(
533
+					'label'      => esc_html__('Preview Deletion', 'event_espresso'),
534
+					'order'      => 15,
535
+					'persistent' => false,
536
+				),
537
+				'require_nonce' => false
538
+			)
539
+		);
540
+	}
541
+
542
+
543
+	/**
544
+	 * Used to register any global screen options if necessary for every route in this admin page group.
545
+	 */
546
+	protected function _add_screen_options()
547
+	{
548
+	}
549
+
550
+
551
+	/**
552
+	 * Implementing the screen options for the 'default' route.
553
+	 */
554
+	protected function _add_screen_options_default()
555
+	{
556
+		$this->_per_page_screen_option();
557
+	}
558
+
559
+
560
+	/**
561
+	 * Implementing screen options for the category list route.
562
+	 */
563
+	protected function _add_screen_options_category_list()
564
+	{
565
+		$page_title = $this->_admin_page_title;
566
+		$this->_admin_page_title = esc_html__('Categories', 'event_espresso');
567
+		$this->_per_page_screen_option();
568
+		$this->_admin_page_title = $page_title;
569
+	}
570
+
571
+
572
+	/**
573
+	 * Used to register any global feature pointers for the admin page group.
574
+	 */
575
+	protected function _add_feature_pointers()
576
+	{
577
+	}
578
+
579
+
580
+	/**
581
+	 * Registers and enqueues any global scripts and styles for the entire admin page group.
582
+	 */
583
+	public function load_scripts_styles()
584
+	{
585
+		wp_register_style(
586
+			'events-admin-css',
587
+			EVENTS_ASSETS_URL . 'events-admin-page.css',
588
+			array(),
589
+			EVENT_ESPRESSO_VERSION
590
+		);
591
+		wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
592
+		wp_enqueue_style('events-admin-css');
593
+		wp_enqueue_style('ee-cat-admin');
594
+		// todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
595
+		// registers for all views
596
+		// scripts
597
+		wp_register_script(
598
+			'event_editor_js',
599
+			EVENTS_ASSETS_URL . 'event_editor.js',
600
+			array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
601
+			EVENT_ESPRESSO_VERSION,
602
+			true
603
+		);
604
+	}
605
+
606
+
607
+	/**
608
+	 * Enqueuing scripts and styles specific to this view
609
+	 */
610
+	public function load_scripts_styles_create_new()
611
+	{
612
+		$this->load_scripts_styles_edit();
613
+	}
614
+
615
+
616
+	/**
617
+	 * Enqueuing scripts and styles specific to this view
618
+	 */
619
+	public function load_scripts_styles_edit()
620
+	{
621
+		// styles
622
+		wp_enqueue_style('espresso-ui-theme');
623
+		wp_register_style(
624
+			'event-editor-css',
625
+			EVENTS_ASSETS_URL . 'event-editor.css',
626
+			array('ee-admin-css'),
627
+			EVENT_ESPRESSO_VERSION
628
+		);
629
+		wp_enqueue_style('event-editor-css');
630
+		// scripts
631
+		wp_register_script(
632
+			'event-datetime-metabox',
633
+			EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
634
+			array('event_editor_js', 'ee-datepicker'),
635
+			EVENT_ESPRESSO_VERSION
636
+		);
637
+		wp_enqueue_script('event-datetime-metabox');
638
+	}
639
+
640
+
641
+	/**
642
+	 * Populating the _views property for the category list table view.
643
+	 */
644
+	protected function _set_list_table_views_category_list()
645
+	{
646
+		$this->_views = array(
647
+			'all' => array(
648
+				'slug'        => 'all',
649
+				'label'       => esc_html__('All', 'event_espresso'),
650
+				'count'       => 0,
651
+				'bulk_action' => array(
652
+					'delete_categories' => esc_html__('Delete Permanently', 'event_espresso'),
653
+				),
654
+			),
655
+		);
656
+	}
657
+
658
+
659
+	/**
660
+	 * For adding anything that fires on the admin_init hook for any route within this admin page group.
661
+	 */
662
+	public function admin_init()
663
+	{
664
+		EE_Registry::$i18n_js_strings['image_confirm'] = esc_html__(
665
+			'Do you really want to delete this image? Please remember to update your event to complete the removal.',
666
+			'event_espresso'
667
+		);
668
+	}
669
+
670
+
671
+	/**
672
+	 * For adding anything that should be triggered on the admin_notices hook for any route within this admin page
673
+	 * group.
674
+	 */
675
+	public function admin_notices()
676
+	{
677
+	}
678
+
679
+
680
+	/**
681
+	 * For adding anything that should be triggered on the `admin_print_footer_scripts` hook for any route within
682
+	 * this admin page group.
683
+	 */
684
+	public function admin_footer_scripts()
685
+	{
686
+	}
687
+
688
+
689
+	/**
690
+	 * Call this function to verify if an event is public and has tickets for sale.  If it does, then we need to show a
691
+	 * warning (via EE_Error::add_error());
692
+	 *
693
+	 * @param  EE_Event $event Event object
694
+	 * @param string    $req_type
695
+	 * @return void
696
+	 * @throws EE_Error
697
+	 * @access public
698
+	 */
699
+	public function verify_event_edit($event = null, $req_type = '')
700
+	{
701
+		// don't need to do this when processing
702
+		if (! empty($req_type)) {
703
+			return;
704
+		}
705
+		// no event?
706
+		if (empty($event)) {
707
+			// set event
708
+			$event = $this->_cpt_model_obj;
709
+		}
710
+		// STILL no event?
711
+		if (! $event instanceof EE_Event) {
712
+			return;
713
+		}
714
+		$orig_status = $event->status();
715
+		// first check if event is active.
716
+		if ($orig_status === EEM_Event::cancelled
717
+			|| $orig_status === EEM_Event::postponed
718
+			|| $event->is_expired()
719
+			|| $event->is_inactive()
720
+		) {
721
+			return;
722
+		}
723
+		// made it here so it IS active... next check that any of the tickets are sold.
724
+		if ($event->is_sold_out(true)) {
725
+			if ($orig_status !== EEM_Event::sold_out && $event->status() !== $orig_status) {
726
+				EE_Error::add_attention(
727
+					sprintf(
728
+						esc_html__(
729
+							'Please note that the Event Status has automatically been changed to %s because there are no more spaces available for this event.  However, this change is not permanent until you update the event.  You can change the status back to something else before updating if you wish.',
730
+							'event_espresso'
731
+						),
732
+						EEH_Template::pretty_status(EEM_Event::sold_out, false, 'sentence')
733
+					)
734
+				);
735
+			}
736
+			return;
737
+		} elseif ($orig_status === EEM_Event::sold_out) {
738
+			EE_Error::add_attention(
739
+				sprintf(
740
+					esc_html__(
741
+						'Please note that the Event Status has automatically been changed to %s because more spaces have become available for this event, most likely due to abandoned transactions freeing up reserved tickets.  However, this change is not permanent until you update the event. If you wish, you can change the status back to something else before updating.',
742
+						'event_espresso'
743
+					),
744
+					EEH_Template::pretty_status($event->status(), false, 'sentence')
745
+				)
746
+			);
747
+		}
748
+		// now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
749
+		if (! $event->tickets_on_sale()) {
750
+			return;
751
+		}
752
+		// made it here so show warning
753
+		$this->_edit_event_warning();
754
+	}
755
+
756
+
757
+	/**
758
+	 * This is the text used for when an event is being edited that is public and has tickets for sale.
759
+	 * When needed, hook this into a EE_Error::add_error() notice.
760
+	 *
761
+	 * @access protected
762
+	 * @return void
763
+	 */
764
+	protected function _edit_event_warning()
765
+	{
766
+		// we don't want to add warnings during these requests
767
+		if (isset($this->_req_data['action']) && $this->_req_data['action'] === 'editpost') {
768
+			return;
769
+		}
770
+		EE_Error::add_attention(
771
+			sprintf(
772
+				esc_html__(
773
+					'Your event is open for registration. Making changes may disrupt any transactions in progress. %sLearn more%s',
774
+					'event_espresso'
775
+				),
776
+				'<a class="espresso-help-tab-lnk">',
777
+				'</a>'
778
+			)
779
+		);
780
+	}
781
+
782
+
783
+	/**
784
+	 * When a user is creating a new event, notify them if they haven't set their timezone.
785
+	 * Otherwise, do the normal logic
786
+	 *
787
+	 * @return string
788
+	 * @throws \EE_Error
789
+	 */
790
+	protected function _create_new_cpt_item()
791
+	{
792
+		$has_timezone_string = get_option('timezone_string');
793
+		// only nag them about setting their timezone if it's their first event, and they haven't already done it
794
+		if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
795
+			EE_Error::add_attention(
796
+				sprintf(
797
+					__(
798
+						'Your website\'s timezone is currently set to a UTC offset. We recommend updating your timezone to a city or region near you before you create an event. Change your timezone now:%1$s%2$s%3$sChange Timezone%4$s',
799
+						'event_espresso'
800
+					),
801
+					'<br>',
802
+					'<select id="timezone_string" name="timezone_string" aria-describedby="timezone-description">'
803
+					. EEH_DTT_Helper::wp_timezone_choice('', EEH_DTT_Helper::get_user_locale())
804
+					. '</select>',
805
+					'<button class="button button-secondary timezone-submit">',
806
+					'</button><span class="spinner"></span>'
807
+				),
808
+				__FILE__,
809
+				__FUNCTION__,
810
+				__LINE__
811
+			);
812
+		}
813
+		return parent::_create_new_cpt_item();
814
+	}
815
+
816
+
817
+	/**
818
+	 * Sets the _views property for the default route in this admin page group.
819
+	 */
820
+	protected function _set_list_table_views_default()
821
+	{
822
+		$this->_views = array(
823
+			'all'   => array(
824
+				'slug'        => 'all',
825
+				'label'       => esc_html__('View All Events', 'event_espresso'),
826
+				'count'       => 0,
827
+				'bulk_action' => array(
828
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
829
+				),
830
+			),
831
+			'draft' => array(
832
+				'slug'        => 'draft',
833
+				'label'       => esc_html__('Draft', 'event_espresso'),
834
+				'count'       => 0,
835
+				'bulk_action' => array(
836
+					'trash_events' => esc_html__('Move to Trash', 'event_espresso'),
837
+				),
838
+			),
839
+		);
840
+		if (EE_Registry::instance()->CAP->current_user_can('ee_delete_events', 'espresso_events_trash_events')) {
841
+			$this->_views['trash'] = array(
842
+				'slug'        => 'trash',
843
+				'label'       => esc_html__('Trash', 'event_espresso'),
844
+				'count'       => 0,
845
+				'bulk_action' => array(
846
+					'restore_events' => esc_html__('Restore From Trash', 'event_espresso'),
847
+					'delete_events'  => esc_html__('Delete Permanently', 'event_espresso'),
848
+				),
849
+			);
850
+		}
851
+	}
852
+
853
+
854
+	/**
855
+	 * Provides the legend item array for the default list table view.
856
+	 *
857
+	 * @return array
858
+	 */
859
+	protected function _event_legend_items()
860
+	{
861
+		$items = array(
862
+			'view_details'   => array(
863
+				'class' => 'dashicons dashicons-search',
864
+				'desc'  => esc_html__('View Event', 'event_espresso'),
865
+			),
866
+			'edit_event'     => array(
867
+				'class' => 'ee-icon ee-icon-calendar-edit',
868
+				'desc'  => esc_html__('Edit Event Details', 'event_espresso'),
869
+			),
870
+			'view_attendees' => array(
871
+				'class' => 'dashicons dashicons-groups',
872
+				'desc'  => esc_html__('View Registrations for Event', 'event_espresso'),
873
+			),
874
+		);
875
+		$items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
876
+		$statuses = array(
877
+			'sold_out_status'  => array(
878
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
879
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
880
+			),
881
+			'active_status'    => array(
882
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
883
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
884
+			),
885
+			'upcoming_status'  => array(
886
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
887
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
888
+			),
889
+			'postponed_status' => array(
890
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
891
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
892
+			),
893
+			'cancelled_status' => array(
894
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
895
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
896
+			),
897
+			'expired_status'   => array(
898
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
899
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
900
+			),
901
+			'inactive_status'  => array(
902
+				'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
903
+				'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
904
+			),
905
+		);
906
+		$statuses = apply_filters('FHEE__Events_Admin_Page__event_legend_items__statuses', $statuses);
907
+		return array_merge($items, $statuses);
908
+	}
909
+
910
+
911
+	/**
912
+	 * @return EEM_Event
913
+	 */
914
+	private function _event_model()
915
+	{
916
+		if (! $this->_event_model instanceof EEM_Event) {
917
+			$this->_event_model = EE_Registry::instance()->load_model('Event');
918
+		}
919
+		return $this->_event_model;
920
+	}
921
+
922
+
923
+	/**
924
+	 * Adds extra buttons to the WP CPT permalink field row.
925
+	 * Method is called from parent and is hooked into the wp 'get_sample_permalink_html' filter.
926
+	 *
927
+	 * @param  string $return    the current html
928
+	 * @param  int    $id        the post id for the page
929
+	 * @param  string $new_title What the title is
930
+	 * @param  string $new_slug  what the slug is
931
+	 * @return string            The new html string for the permalink area
932
+	 */
933
+	public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
934
+	{
935
+		// make sure this is only when editing
936
+		if (! empty($id)) {
937
+			$post = get_post($id);
938
+			$return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
939
+					   . esc_html__('Shortcode', 'event_espresso')
940
+					   . '</a> ';
941
+			$return .= '<input id="shortcode" type="hidden" value="[ESPRESSO_TICKET_SELECTOR event_id='
942
+					   . $post->ID
943
+					   . ']">';
944
+		}
945
+		return $return;
946
+	}
947
+
948
+
949
+	/**
950
+	 * _events_overview_list_table
951
+	 * This contains the logic for showing the events_overview list
952
+	 *
953
+	 * @access protected
954
+	 * @return void
955
+	 * @throws \EE_Error
956
+	 */
957
+	protected function _events_overview_list_table()
958
+	{
959
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
960
+		$this->_template_args['after_list_table'] = ! empty($this->_template_args['after_list_table'])
961
+			? (array) $this->_template_args['after_list_table']
962
+			: array();
963
+		$this->_template_args['after_list_table']['view_event_list_button'] = EEH_HTML::br()
964
+				. EEH_Template::get_button_or_link(
965
+					get_post_type_archive_link('espresso_events'),
966
+					esc_html__("View Event Archive Page", "event_espresso"),
967
+					'button'
968
+				);
969
+		$this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
970
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
971
+			'create_new',
972
+			'add',
973
+			array(),
974
+			'add-new-h2'
975
+		);
976
+		$this->display_admin_list_table_page_with_no_sidebar();
977
+	}
978
+
979
+
980
+	/**
981
+	 * this allows for extra misc actions in the default WP publish box
982
+	 *
983
+	 * @return void
984
+	 */
985
+	public function extra_misc_actions_publish_box()
986
+	{
987
+		$this->_generate_publish_box_extra_content();
988
+	}
989
+
990
+
991
+	/**
992
+	 * This is hooked into the WordPress do_action('save_post') hook and runs after the custom post type has been
993
+	 * saved.
994
+	 * Typically you would use this to save any additional data.
995
+	 * Keep in mind also that "save_post" runs on EVERY post update to the database.
996
+	 * ALSO very important.  When a post transitions from scheduled to published,
997
+	 * the save_post action is fired but you will NOT have any _POST data containing any extra info you may have from
998
+	 * other meta saves. So MAKE sure that you handle this accordingly.
999
+	 *
1000
+	 * @access protected
1001
+	 * @abstract
1002
+	 * @param  string $post_id The ID of the cpt that was saved (so you can link relationally)
1003
+	 * @param  object $post    The post object of the cpt that was saved.
1004
+	 * @return void
1005
+	 * @throws \EE_Error
1006
+	 */
1007
+	protected function _insert_update_cpt_item($post_id, $post)
1008
+	{
1009
+		if ($post instanceof WP_Post && $post->post_type !== 'espresso_events') {
1010
+			// get out we're not processing an event save.
1011
+			return;
1012
+		}
1013
+		$event_values = array(
1014
+			'EVT_display_desc'                => ! empty($this->_req_data['display_desc']) ? 1 : 0,
1015
+			'EVT_display_ticket_selector'     => ! empty($this->_req_data['display_ticket_selector']) ? 1 : 0,
1016
+			'EVT_additional_limit'            => min(
1017
+				apply_filters('FHEE__EE_Events_Admin__insert_update_cpt_item__EVT_additional_limit_max', 255),
1018
+				! empty($this->_req_data['additional_limit']) ? $this->_req_data['additional_limit'] : null
1019
+			),
1020
+			'EVT_default_registration_status' => ! empty($this->_req_data['EVT_default_registration_status'])
1021
+				? $this->_req_data['EVT_default_registration_status']
1022
+				: EE_Registry::instance()->CFG->registration->default_STS_ID,
1023
+			'EVT_member_only'                 => ! empty($this->_req_data['member_only']) ? 1 : 0,
1024
+			'EVT_allow_overflow'              => ! empty($this->_req_data['EVT_allow_overflow']) ? 1 : 0,
1025
+			'EVT_timezone_string'             => ! empty($this->_req_data['timezone_string'])
1026
+				? $this->_req_data['timezone_string'] : null,
1027
+			'EVT_external_URL'                => ! empty($this->_req_data['externalURL'])
1028
+				? $this->_req_data['externalURL'] : null,
1029
+			'EVT_phone'                       => ! empty($this->_req_data['event_phone'])
1030
+				? $this->_req_data['event_phone'] : null,
1031
+		);
1032
+		// update event
1033
+		$success = $this->_event_model()->update_by_ID($event_values, $post_id);
1034
+		// get event_object for other metaboxes... though it would seem to make sense to just use $this->_event_model()->get_one_by_ID( $post_id ).. i have to setup where conditions to override the filters in the model that filter out autodraft and inherit statuses so we GET the inherit id!
1035
+		$get_one_where = array(
1036
+			$this->_event_model()->primary_key_name() => $post_id,
1037
+			'OR'                                      => array(
1038
+				'status'   => $post->post_status,
1039
+				// if trying to "Publish" a sold out event, it's status will get switched back to "sold_out" in the db,
1040
+				// but the returned object here has a status of "publish", so use the original post status as well
1041
+				'status*1' => $this->_req_data['original_post_status'],
1042
+			),
1043
+		);
1044
+		$event = $this->_event_model()->get_one(array($get_one_where));
1045
+		// the following are default callbacks for event attachment updates that can be overridden by caffeinated functionality and/or addons.
1046
+		$event_update_callbacks = apply_filters(
1047
+			'FHEE__Events_Admin_Page___insert_update_cpt_item__event_update_callbacks',
1048
+			array(
1049
+				array($this, '_default_venue_update'),
1050
+				array($this, '_default_tickets_update'),
1051
+			)
1052
+		);
1053
+		$att_success = true;
1054
+		foreach ($event_update_callbacks as $e_callback) {
1055
+			$_success = is_callable($e_callback)
1056
+				? call_user_func($e_callback, $event, $this->_req_data)
1057
+				: false;
1058
+			// if ANY of these updates fail then we want the appropriate global error message
1059
+			$att_success = ! $att_success ? $att_success : $_success;
1060
+		}
1061
+		// any errors?
1062
+		if ($success && false === $att_success) {
1063
+			EE_Error::add_error(
1064
+				esc_html__(
1065
+					'Event Details saved successfully but something went wrong with saving attachments.',
1066
+					'event_espresso'
1067
+				),
1068
+				__FILE__,
1069
+				__FUNCTION__,
1070
+				__LINE__
1071
+			);
1072
+		} elseif ($success === false) {
1073
+			EE_Error::add_error(
1074
+				esc_html__('Event Details did not save successfully.', 'event_espresso'),
1075
+				__FILE__,
1076
+				__FUNCTION__,
1077
+				__LINE__
1078
+			);
1079
+		}
1080
+	}
1081
+
1082
+
1083
+	/**
1084
+	 * @see parent::restore_item()
1085
+	 * @param int $post_id
1086
+	 * @param int $revision_id
1087
+	 */
1088
+	protected function _restore_cpt_item($post_id, $revision_id)
1089
+	{
1090
+		// copy existing event meta to new post
1091
+		$post_evt = $this->_event_model()->get_one_by_ID($post_id);
1092
+		if ($post_evt instanceof EE_Event) {
1093
+			// meta revision restore
1094
+			$post_evt->restore_revision($revision_id);
1095
+			// related objs restore
1096
+			$post_evt->restore_revision($revision_id, array('Venue', 'Datetime', 'Price'));
1097
+		}
1098
+	}
1099
+
1100
+
1101
+	/**
1102
+	 * Attach the venue to the Event
1103
+	 *
1104
+	 * @param  \EE_Event $evtobj Event Object to add the venue to
1105
+	 * @param  array     $data   The request data from the form
1106
+	 * @return bool           Success or fail.
1107
+	 */
1108
+	protected function _default_venue_update(\EE_Event $evtobj, $data)
1109
+	{
1110
+		require_once(EE_MODELS . 'EEM_Venue.model.php');
1111
+		$venue_model = EE_Registry::instance()->load_model('Venue');
1112
+		$rows_affected = null;
1113
+		$venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
1114
+		// very important.  If we don't have a venue name...
1115
+		// then we'll get out because not necessary to create empty venue
1116
+		if (empty($data['venue_title'])) {
1117
+			return false;
1118
+		}
1119
+		$venue_array = array(
1120
+			'VNU_wp_user'         => $evtobj->get('EVT_wp_user'),
1121
+			'VNU_name'            => ! empty($data['venue_title']) ? $data['venue_title'] : null,
1122
+			'VNU_desc'            => ! empty($data['venue_description']) ? $data['venue_description'] : null,
1123
+			'VNU_identifier'      => ! empty($data['venue_identifier']) ? $data['venue_identifier'] : null,
1124
+			'VNU_short_desc'      => ! empty($data['venue_short_description']) ? $data['venue_short_description']
1125
+				: null,
1126
+			'VNU_address'         => ! empty($data['address']) ? $data['address'] : null,
1127
+			'VNU_address2'        => ! empty($data['address2']) ? $data['address2'] : null,
1128
+			'VNU_city'            => ! empty($data['city']) ? $data['city'] : null,
1129
+			'STA_ID'              => ! empty($data['state']) ? $data['state'] : null,
1130
+			'CNT_ISO'             => ! empty($data['countries']) ? $data['countries'] : null,
1131
+			'VNU_zip'             => ! empty($data['zip']) ? $data['zip'] : null,
1132
+			'VNU_phone'           => ! empty($data['venue_phone']) ? $data['venue_phone'] : null,
1133
+			'VNU_capacity'        => ! empty($data['venue_capacity']) ? $data['venue_capacity'] : null,
1134
+			'VNU_url'             => ! empty($data['venue_url']) ? $data['venue_url'] : null,
1135
+			'VNU_virtual_phone'   => ! empty($data['virtual_phone']) ? $data['virtual_phone'] : null,
1136
+			'VNU_virtual_url'     => ! empty($data['virtual_url']) ? $data['virtual_url'] : null,
1137
+			'VNU_enable_for_gmap' => isset($data['enable_for_gmap']) ? 1 : 0,
1138
+			'status'              => 'publish',
1139
+		);
1140
+		// if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1141
+		if (! empty($venue_id)) {
1142
+			$update_where = array($venue_model->primary_key_name() => $venue_id);
1143
+			$rows_affected = $venue_model->update($venue_array, array($update_where));
1144
+			// we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
1145
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1146
+			return $rows_affected > 0 ? true : false;
1147
+		} else {
1148
+			// we insert the venue
1149
+			$venue_id = $venue_model->insert($venue_array);
1150
+			$evtobj->_add_relation_to($venue_id, 'Venue');
1151
+			return ! empty($venue_id) ? true : false;
1152
+		}
1153
+		// when we have the ancestor come in it's already been handled by the revision save.
1154
+	}
1155
+
1156
+
1157
+	/**
1158
+	 * Handles saving everything related to Tickets (datetimes, tickets, prices)
1159
+	 *
1160
+	 * @param  EE_Event $evtobj The Event object we're attaching data to
1161
+	 * @param  array    $data   The request data from the form
1162
+	 * @return array
1163
+	 */
1164
+	protected function _default_tickets_update(EE_Event $evtobj, $data)
1165
+	{
1166
+		$success = true;
1167
+		$saved_dtt = null;
1168
+		$saved_tickets = array();
1169
+		$incoming_date_formats = array('Y-m-d', 'h:i a');
1170
+		foreach ($data['edit_event_datetimes'] as $row => $dtt) {
1171
+			// trim all values to ensure any excess whitespace is removed.
1172
+			$dtt = array_map('trim', $dtt);
1173
+			$dtt['DTT_EVT_end'] = isset($dtt['DTT_EVT_end']) && ! empty($dtt['DTT_EVT_end']) ? $dtt['DTT_EVT_end']
1174
+				: $dtt['DTT_EVT_start'];
1175
+			$datetime_values = array(
1176
+				'DTT_ID'        => ! empty($dtt['DTT_ID']) ? $dtt['DTT_ID'] : null,
1177
+				'DTT_EVT_start' => $dtt['DTT_EVT_start'],
1178
+				'DTT_EVT_end'   => $dtt['DTT_EVT_end'],
1179
+				'DTT_reg_limit' => empty($dtt['DTT_reg_limit']) ? EE_INF : $dtt['DTT_reg_limit'],
1180
+				'DTT_order'     => $row,
1181
+			);
1182
+			// if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1183
+			if (! empty($dtt['DTT_ID'])) {
1184
+				$DTM = EE_Registry::instance()
1185
+								  ->load_model('Datetime', array($evtobj->get_timezone()))
1186
+								  ->get_one_by_ID($dtt['DTT_ID']);
1187
+				$DTM->set_date_format($incoming_date_formats[0]);
1188
+				$DTM->set_time_format($incoming_date_formats[1]);
1189
+				foreach ($datetime_values as $field => $value) {
1190
+					$DTM->set($field, $value);
1191
+				}
1192
+				// make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1193
+				$saved_dtts[ $DTM->ID() ] = $DTM;
1194
+			} else {
1195
+				$DTM = EE_Registry::instance()->load_class(
1196
+					'Datetime',
1197
+					array($datetime_values, $evtobj->get_timezone(), $incoming_date_formats),
1198
+					false,
1199
+					false
1200
+				);
1201
+				foreach ($datetime_values as $field => $value) {
1202
+					$DTM->set($field, $value);
1203
+				}
1204
+			}
1205
+			$DTM->save();
1206
+			$DTT = $evtobj->_add_relation_to($DTM, 'Datetime');
1207
+			// load DTT helper
1208
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1209
+			if ($DTT->get_raw('DTT_EVT_start') > $DTT->get_raw('DTT_EVT_end')) {
1210
+				$DTT->set('DTT_EVT_end', $DTT->get('DTT_EVT_start'));
1211
+				$DTT = EEH_DTT_Helper::date_time_add($DTT, 'DTT_EVT_end', 'days');
1212
+				$DTT->save();
1213
+			}
1214
+			// now we got to make sure we add the new DTT_ID to the $saved_dtts array  because it is possible there was a new one created for the autosave.
1215
+			$saved_dtt = $DTT;
1216
+			$success = ! $success ? $success : $DTT;
1217
+			// if ANY of these updates fail then we want the appropriate global error message.
1218
+			// //todo this is actually sucky we need a better error message but this is what it is for now.
1219
+		}
1220
+		// no dtts get deleted so we don't do any of that logic here.
1221
+		// update tickets next
1222
+		$old_tickets = isset($data['ticket_IDs']) ? explode(',', $data['ticket_IDs']) : array();
1223
+		foreach ($data['edit_tickets'] as $row => $tkt) {
1224
+			$incoming_date_formats = array('Y-m-d', 'h:i a');
1225
+			$update_prices = false;
1226
+			$ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1227
+				? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1228
+			// trim inputs to ensure any excess whitespace is removed.
1229
+			$tkt = array_map('trim', $tkt);
1230
+			if (empty($tkt['TKT_start_date'])) {
1231
+				// let's use now in the set timezone.
1232
+				$now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1233
+				$tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1234
+			}
1235
+			if (empty($tkt['TKT_end_date'])) {
1236
+				// use the start date of the first datetime
1237
+				$dtt = $evtobj->first_datetime();
1238
+				$tkt['TKT_end_date'] = $dtt->start_date_and_time(
1239
+					$incoming_date_formats[0],
1240
+					$incoming_date_formats[1]
1241
+				);
1242
+			}
1243
+			$TKT_values = array(
1244
+				'TKT_ID'          => ! empty($tkt['TKT_ID']) ? $tkt['TKT_ID'] : null,
1245
+				'TTM_ID'          => ! empty($tkt['TTM_ID']) ? $tkt['TTM_ID'] : 0,
1246
+				'TKT_name'        => ! empty($tkt['TKT_name']) ? $tkt['TKT_name'] : '',
1247
+				'TKT_description' => ! empty($tkt['TKT_description']) ? $tkt['TKT_description'] : '',
1248
+				'TKT_start_date'  => $tkt['TKT_start_date'],
1249
+				'TKT_end_date'    => $tkt['TKT_end_date'],
1250
+				'TKT_qty'         => ! isset($tkt['TKT_qty']) || $tkt['TKT_qty'] === '' ? EE_INF : $tkt['TKT_qty'],
1251
+				'TKT_uses'        => ! isset($tkt['TKT_uses']) || $tkt['TKT_uses'] === '' ? EE_INF : $tkt['TKT_uses'],
1252
+				'TKT_min'         => empty($tkt['TKT_min']) ? 0 : $tkt['TKT_min'],
1253
+				'TKT_max'         => empty($tkt['TKT_max']) ? EE_INF : $tkt['TKT_max'],
1254
+				'TKT_row'         => $row,
1255
+				'TKT_order'       => isset($tkt['TKT_order']) ? $tkt['TKT_order'] : $row,
1256
+				'TKT_price'       => $ticket_price,
1257
+			);
1258
+			// if this is a default TKT, then we need to set the TKT_ID to 0 and update accordingly, which means in turn that the prices will become new prices as well.
1259
+			if (isset($tkt['TKT_is_default']) && $tkt['TKT_is_default']) {
1260
+				$TKT_values['TKT_ID'] = 0;
1261
+				$TKT_values['TKT_is_default'] = 0;
1262
+				$TKT_values['TKT_price'] = $ticket_price;
1263
+				$update_prices = true;
1264
+			}
1265
+			// if we have a TKT_ID then we need to get that existing TKT_obj and update it
1266
+			// we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1267
+			// keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1268
+			if (! empty($tkt['TKT_ID'])) {
1269
+				$TKT = EE_Registry::instance()
1270
+								  ->load_model('Ticket', array($evtobj->get_timezone()))
1271
+								  ->get_one_by_ID($tkt['TKT_ID']);
1272
+				if ($TKT instanceof EE_Ticket) {
1273
+					$ticket_sold = $TKT->count_related(
1274
+						'Registration',
1275
+						array(
1276
+							array(
1277
+								'STS_ID' => array(
1278
+									'NOT IN',
1279
+									array(EEM_Registration::status_id_incomplete),
1280
+								),
1281
+							),
1282
+						)
1283
+					) > 0 ? true : false;
1284
+					// let's just check the total price for the existing ticket and determine if it matches the new total price.  if they are different then we create a new ticket (if tkts sold) if they aren't different then we go ahead and modify existing ticket.
1285
+					$create_new_TKT = $ticket_sold && $ticket_price != $TKT->get('TKT_price')
1286
+									  && ! $TKT->get('TKT_deleted');
1287
+					$TKT->set_date_format($incoming_date_formats[0]);
1288
+					$TKT->set_time_format($incoming_date_formats[1]);
1289
+					// set new values
1290
+					foreach ($TKT_values as $field => $value) {
1291
+						if ($field == 'TKT_qty') {
1292
+							$TKT->set_qty($value);
1293
+						} else {
1294
+							$TKT->set($field, $value);
1295
+						}
1296
+					}
1297
+					// if $create_new_TKT is false then we can safely update the existing ticket.  Otherwise we have to create a new ticket.
1298
+					if ($create_new_TKT) {
1299
+						// archive the old ticket first
1300
+						$TKT->set('TKT_deleted', 1);
1301
+						$TKT->save();
1302
+						// make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1303
+						$saved_tickets[ $TKT->ID() ] = $TKT;
1304
+						// create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1305
+						$TKT = clone $TKT;
1306
+						$TKT->set('TKT_ID', 0);
1307
+						$TKT->set('TKT_deleted', 0);
1308
+						$TKT->set('TKT_price', $ticket_price);
1309
+						$TKT->set('TKT_sold', 0);
1310
+						// now we need to make sure that $new prices are created as well and attached to new ticket.
1311
+						$update_prices = true;
1312
+					}
1313
+					// make sure price is set if it hasn't been already
1314
+					$TKT->set('TKT_price', $ticket_price);
1315
+				}
1316
+			} else {
1317
+				// no TKT_id so a new TKT
1318
+				$TKT_values['TKT_price'] = $ticket_price;
1319
+				$TKT = EE_Registry::instance()->load_class('Ticket', array($TKT_values), false, false);
1320
+				if ($TKT instanceof EE_Ticket) {
1321
+					// need to reset values to properly account for the date formats
1322
+					$TKT->set_date_format($incoming_date_formats[0]);
1323
+					$TKT->set_time_format($incoming_date_formats[1]);
1324
+					$TKT->set_timezone($evtobj->get_timezone());
1325
+					// set new values
1326
+					foreach ($TKT_values as $field => $value) {
1327
+						if ($field == 'TKT_qty') {
1328
+							$TKT->set_qty($value);
1329
+						} else {
1330
+							$TKT->set($field, $value);
1331
+						}
1332
+					}
1333
+					$update_prices = true;
1334
+				}
1335
+			}
1336
+			// cap ticket qty by datetime reg limits
1337
+			$TKT->set_qty(min($TKT->qty(), $TKT->qty('reg_limit')));
1338
+			// update ticket.
1339
+			$TKT->save();
1340
+			// before going any further make sure our dates are setup correctly so that the end date is always equal or greater than the start date.
1341
+			if ($TKT->get_raw('TKT_start_date') > $TKT->get_raw('TKT_end_date')) {
1342
+				$TKT->set('TKT_end_date', $TKT->get('TKT_start_date'));
1343
+				$TKT = EEH_DTT_Helper::date_time_add($TKT, 'TKT_end_date', 'days');
1344
+				$TKT->save();
1345
+			}
1346
+			// initially let's add the ticket to the dtt
1347
+			$saved_dtt->_add_relation_to($TKT, 'Ticket');
1348
+			$saved_tickets[ $TKT->ID() ] = $TKT;
1349
+			// add prices to ticket
1350
+			$this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1351
+		}
1352
+		// however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1353
+		$old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
1354
+		$tickets_removed = array_diff($old_tickets, array_keys($saved_tickets));
1355
+		foreach ($tickets_removed as $id) {
1356
+			$id = absint($id);
1357
+			// get the ticket for this id
1358
+			$tkt_to_remove = EE_Registry::instance()->load_model('Ticket')->get_one_by_ID($id);
1359
+			// need to get all the related datetimes on this ticket and remove from every single one of them (remember this process can ONLY kick off if there are NO tkts_sold)
1360
+			$dtts = $tkt_to_remove->get_many_related('Datetime');
1361
+			foreach ($dtts as $dtt) {
1362
+				$tkt_to_remove->_remove_relation_to($dtt, 'Datetime');
1363
+			}
1364
+			// need to do the same for prices (except these prices can also be deleted because again, tickets can only be trashed if they don't have any TKTs sold (otherwise they are just archived))
1365
+			$tkt_to_remove->delete_related_permanently('Price');
1366
+			// finally let's delete this ticket (which should not be blocked at this point b/c we've removed all our relationships)
1367
+			$tkt_to_remove->delete_permanently();
1368
+		}
1369
+		return array($saved_dtt, $saved_tickets);
1370
+	}
1371
+
1372
+
1373
+	/**
1374
+	 * This attaches a list of given prices to a ticket.
1375
+	 * Note we dont' have to worry about ever removing relationships (or archiving prices) because if there is a change
1376
+	 * in price information on a ticket, a new ticket is created anyways so the archived ticket will retain the old
1377
+	 * price info and prices are automatically "archived" via the ticket.
1378
+	 *
1379
+	 * @access  private
1380
+	 * @param array     $prices     Array of prices from the form.
1381
+	 * @param EE_Ticket $ticket     EE_Ticket object that prices are being attached to.
1382
+	 * @param bool      $new_prices Whether attach existing incoming prices or create new ones.
1383
+	 * @return  void
1384
+	 */
1385
+	private function _add_prices_to_ticket($prices, EE_Ticket $ticket, $new_prices = false)
1386
+	{
1387
+		foreach ($prices as $row => $prc) {
1388
+			$PRC_values = array(
1389
+				'PRC_ID'         => ! empty($prc['PRC_ID']) ? $prc['PRC_ID'] : null,
1390
+				'PRT_ID'         => ! empty($prc['PRT_ID']) ? $prc['PRT_ID'] : null,
1391
+				'PRC_amount'     => ! empty($prc['PRC_amount']) ? $prc['PRC_amount'] : 0,
1392
+				'PRC_name'       => ! empty($prc['PRC_name']) ? $prc['PRC_name'] : '',
1393
+				'PRC_desc'       => ! empty($prc['PRC_desc']) ? $prc['PRC_desc'] : '',
1394
+				'PRC_is_default' => 0, // make sure prices are NOT set as default from this context
1395
+				'PRC_order'      => $row,
1396
+			);
1397
+			if ($new_prices || empty($PRC_values['PRC_ID'])) {
1398
+				$PRC_values['PRC_ID'] = 0;
1399
+				$PRC = EE_Registry::instance()->load_class('Price', array($PRC_values), false, false);
1400
+			} else {
1401
+				$PRC = EE_Registry::instance()->load_model('Price')->get_one_by_ID($prc['PRC_ID']);
1402
+				// update this price with new values
1403
+				foreach ($PRC_values as $field => $newprc) {
1404
+					$PRC->set($field, $newprc);
1405
+				}
1406
+				$PRC->save();
1407
+			}
1408
+			$ticket->_add_relation_to($PRC, 'Price');
1409
+		}
1410
+	}
1411
+
1412
+
1413
+	/**
1414
+	 * Add in our autosave ajax handlers
1415
+	 *
1416
+	 */
1417
+	protected function _ee_autosave_create_new()
1418
+	{
1419
+	}
1420
+
1421
+
1422
+	/**
1423
+	 * More autosave handlers.
1424
+	 */
1425
+	protected function _ee_autosave_edit()
1426
+	{
1427
+		return; // TEMPORARILY EXITING CAUSE THIS IS A TODO
1428
+	}
1429
+
1430
+
1431
+	/**
1432
+	 *    _generate_publish_box_extra_content
1433
+	 */
1434
+	private function _generate_publish_box_extra_content()
1435
+	{
1436
+		// load formatter helper
1437
+		// args for getting related registrations
1438
+		$approved_query_args = array(
1439
+			array(
1440
+				'REG_deleted' => 0,
1441
+				'STS_ID'      => EEM_Registration::status_id_approved,
1442
+			),
1443
+		);
1444
+		$not_approved_query_args = array(
1445
+			array(
1446
+				'REG_deleted' => 0,
1447
+				'STS_ID'      => EEM_Registration::status_id_not_approved,
1448
+			),
1449
+		);
1450
+		$pending_payment_query_args = array(
1451
+			array(
1452
+				'REG_deleted' => 0,
1453
+				'STS_ID'      => EEM_Registration::status_id_pending_payment,
1454
+			),
1455
+		);
1456
+		// publish box
1457
+		$publish_box_extra_args = array(
1458
+			'view_approved_reg_url'        => add_query_arg(
1459
+				array(
1460
+					'action'      => 'default',
1461
+					'event_id'    => $this->_cpt_model_obj->ID(),
1462
+					'_reg_status' => EEM_Registration::status_id_approved,
1463
+				),
1464
+				REG_ADMIN_URL
1465
+			),
1466
+			'view_not_approved_reg_url'    => add_query_arg(
1467
+				array(
1468
+					'action'      => 'default',
1469
+					'event_id'    => $this->_cpt_model_obj->ID(),
1470
+					'_reg_status' => EEM_Registration::status_id_not_approved,
1471
+				),
1472
+				REG_ADMIN_URL
1473
+			),
1474
+			'view_pending_payment_reg_url' => add_query_arg(
1475
+				array(
1476
+					'action'      => 'default',
1477
+					'event_id'    => $this->_cpt_model_obj->ID(),
1478
+					'_reg_status' => EEM_Registration::status_id_pending_payment,
1479
+				),
1480
+				REG_ADMIN_URL
1481
+			),
1482
+			'approved_regs'                => $this->_cpt_model_obj->count_related(
1483
+				'Registration',
1484
+				$approved_query_args
1485
+			),
1486
+			'not_approved_regs'            => $this->_cpt_model_obj->count_related(
1487
+				'Registration',
1488
+				$not_approved_query_args
1489
+			),
1490
+			'pending_payment_regs'         => $this->_cpt_model_obj->count_related(
1491
+				'Registration',
1492
+				$pending_payment_query_args
1493
+			),
1494
+			'misc_pub_section_class'       => apply_filters(
1495
+				'FHEE_Events_Admin_Page___generate_publish_box_extra_content__misc_pub_section_class',
1496
+				'misc-pub-section'
1497
+			),
1498
+		);
1499
+		ob_start();
1500
+		do_action(
1501
+			'AHEE__Events_Admin_Page___generate_publish_box_extra_content__event_editor_overview_add',
1502
+			$this->_cpt_model_obj
1503
+		);
1504
+		$publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1505
+		// load template
1506
+		EEH_Template::display_template(
1507
+			EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1508
+			$publish_box_extra_args
1509
+		);
1510
+	}
1511
+
1512
+
1513
+	/**
1514
+	 * @return EE_Event
1515
+	 */
1516
+	public function get_event_object()
1517
+	{
1518
+		return $this->_cpt_model_obj;
1519
+	}
1520
+
1521
+
1522
+
1523
+
1524
+	/** METABOXES * */
1525
+	/**
1526
+	 * _register_event_editor_meta_boxes
1527
+	 * add all metaboxes related to the event_editor
1528
+	 *
1529
+	 * @return void
1530
+	 */
1531
+	protected function _register_event_editor_meta_boxes()
1532
+	{
1533
+		$this->verify_cpt_object();
1534
+		add_meta_box(
1535
+			'espresso_event_editor_tickets',
1536
+			esc_html__('Event Datetime & Ticket', 'event_espresso'),
1537
+			array($this, 'ticket_metabox'),
1538
+			$this->page_slug,
1539
+			'normal',
1540
+			'high'
1541
+		);
1542
+		add_meta_box(
1543
+			'espresso_event_editor_event_options',
1544
+			esc_html__('Event Registration Options', 'event_espresso'),
1545
+			array($this, 'registration_options_meta_box'),
1546
+			$this->page_slug,
1547
+			'side',
1548
+			'default'
1549
+		);
1550
+		// NOTE: if you're looking for other metaboxes in here,
1551
+		// where a metabox has a related management page in the admin
1552
+		// you will find it setup in the related management page's "_Hooks" file.
1553
+		// i.e. messages metabox is found in "espresso_events_Messages_Hooks.class.php".
1554
+	}
1555
+
1556
+
1557
+	/**
1558
+	 * @throws DomainException
1559
+	 * @throws EE_Error
1560
+	 */
1561
+	public function ticket_metabox()
1562
+	{
1563
+		$existing_datetime_ids = $existing_ticket_ids = array();
1564
+		// defaults for template args
1565
+		$template_args = array(
1566
+			'existing_datetime_ids'    => '',
1567
+			'event_datetime_help_link' => '',
1568
+			'ticket_options_help_link' => '',
1569
+			'time'                     => null,
1570
+			'ticket_rows'              => '',
1571
+			'existing_ticket_ids'      => '',
1572
+			'total_ticket_rows'        => 1,
1573
+			'ticket_js_structure'      => '',
1574
+			'trash_icon'               => 'ee-lock-icon',
1575
+			'disabled'                 => '',
1576
+		);
1577
+		$event_id = is_object($this->_cpt_model_obj) ? $this->_cpt_model_obj->ID() : null;
1578
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
1579
+		/**
1580
+		 * 1. Start with retrieving Datetimes
1581
+		 * 2. Fore each datetime get related tickets
1582
+		 * 3. For each ticket get related prices
1583
+		 */
1584
+		$times = EE_Registry::instance()->load_model('Datetime')->get_all_event_dates($event_id);
1585
+		/** @type EE_Datetime $first_datetime */
1586
+		$first_datetime = reset($times);
1587
+		// do we get related tickets?
1588
+		if ($first_datetime instanceof EE_Datetime
1589
+			&& $first_datetime->ID() !== 0
1590
+		) {
1591
+			$existing_datetime_ids[] = $first_datetime->get('DTT_ID');
1592
+			$template_args['time'] = $first_datetime;
1593
+			$related_tickets = $first_datetime->tickets(
1594
+				array(
1595
+					array('OR' => array('TKT_deleted' => 1, 'TKT_deleted*' => 0)),
1596
+					'default_where_conditions' => 'none',
1597
+				)
1598
+			);
1599
+			if (! empty($related_tickets)) {
1600
+				$template_args['total_ticket_rows'] = count($related_tickets);
1601
+				$row = 0;
1602
+				foreach ($related_tickets as $ticket) {
1603
+					$existing_ticket_ids[] = $ticket->get('TKT_ID');
1604
+					$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket, false, $row);
1605
+					$row++;
1606
+				}
1607
+			} else {
1608
+				$template_args['total_ticket_rows'] = 1;
1609
+				/** @type EE_Ticket $ticket */
1610
+				$ticket = EE_Registry::instance()->load_model('Ticket')->create_default_object();
1611
+				$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket);
1612
+			}
1613
+		} else {
1614
+			$template_args['time'] = $times[0];
1615
+			/** @type EE_Ticket $ticket */
1616
+			$ticket = EE_Registry::instance()->load_model('Ticket')->get_all_default_tickets();
1617
+			$template_args['ticket_rows'] .= $this->_get_ticket_row($ticket[1]);
1618
+			// NOTE: we're just sending the first default row
1619
+			// (decaf can't manage default tickets so this should be sufficient);
1620
+		}
1621
+		$template_args['event_datetime_help_link'] = $this->_get_help_tab_link(
1622
+			'event_editor_event_datetimes_help_tab'
1623
+		);
1624
+		$template_args['ticket_options_help_link'] = $this->_get_help_tab_link('ticket_options_info');
1625
+		$template_args['existing_datetime_ids'] = implode(',', $existing_datetime_ids);
1626
+		$template_args['existing_ticket_ids'] = implode(',', $existing_ticket_ids);
1627
+		$template_args['ticket_js_structure'] = $this->_get_ticket_row(
1628
+			EE_Registry::instance()->load_model('Ticket')->create_default_object(),
1629
+			true
1630
+		);
1631
+		$template = apply_filters(
1632
+			'FHEE__Events_Admin_Page__ticket_metabox__template',
1633
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1634
+		);
1635
+		EEH_Template::display_template($template, $template_args);
1636
+	}
1637
+
1638
+
1639
+	/**
1640
+	 * Setup an individual ticket form for the decaf event editor page
1641
+	 *
1642
+	 * @access private
1643
+	 * @param  EE_Ticket $ticket   the ticket object
1644
+	 * @param  boolean   $skeleton whether we're generating a skeleton for js manipulation
1645
+	 * @param int        $row
1646
+	 * @return string generated html for the ticket row.
1647
+	 */
1648
+	private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1649
+	{
1650
+		$template_args = array(
1651
+			'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1652
+			'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1653
+				: '',
1654
+			'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
1655
+			'TKT_ID'              => $ticket->get('TKT_ID'),
1656
+			'TKT_name'            => $ticket->get('TKT_name'),
1657
+			'TKT_start_date'      => $skeleton ? '' : $ticket->get_date('TKT_start_date', 'Y-m-d h:i a'),
1658
+			'TKT_end_date'        => $skeleton ? '' : $ticket->get_date('TKT_end_date', 'Y-m-d h:i a'),
1659
+			'TKT_is_default'      => $ticket->get('TKT_is_default'),
1660
+			'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1661
+			'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1662
+			'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1663
+			'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1664
+									 && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1665
+				? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1666
+			'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1667
+				: ' disabled=disabled',
1668
+		);
1669
+		$price = $ticket->ID() !== 0
1670
+			? $ticket->get_first_related('Price', array('default_where_conditions' => 'none'))
1671
+			: EE_Registry::instance()->load_model('Price')->create_default_object();
1672
+		$price_args = array(
1673
+			'price_currency_symbol' => EE_Registry::instance()->CFG->currency->sign,
1674
+			'PRC_amount'            => $price->get('PRC_amount'),
1675
+			'PRT_ID'                => $price->get('PRT_ID'),
1676
+			'PRC_ID'                => $price->get('PRC_ID'),
1677
+			'PRC_is_default'        => $price->get('PRC_is_default'),
1678
+		);
1679
+		// make sure we have default start and end dates if skeleton
1680
+		// handle rows that should NOT be empty
1681
+		if (empty($template_args['TKT_start_date'])) {
1682
+			// if empty then the start date will be now.
1683
+			$template_args['TKT_start_date'] = date('Y-m-d h:i a', current_time('timestamp'));
1684
+		}
1685
+		if (empty($template_args['TKT_end_date'])) {
1686
+			// get the earliest datetime (if present);
1687
+			$earliest_dtt = $this->_cpt_model_obj->ID() > 0
1688
+				? $this->_cpt_model_obj->get_first_related(
1689
+					'Datetime',
1690
+					array('order_by' => array('DTT_EVT_start' => 'ASC'))
1691
+				)
1692
+				: null;
1693
+			if (! empty($earliest_dtt)) {
1694
+				$template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1695
+			} else {
1696
+				$template_args['TKT_end_date'] = date(
1697
+					'Y-m-d h:i a',
1698
+					mktime(0, 0, 0, date("m"), date("d") + 7, date("Y"))
1699
+				);
1700
+			}
1701
+		}
1702
+		$template_args = array_merge($template_args, $price_args);
1703
+		$template = apply_filters(
1704
+			'FHEE__Events_Admin_Page__get_ticket_row__template',
1705
+			EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1706
+			$ticket
1707
+		);
1708
+		return EEH_Template::display_template($template, $template_args, true);
1709
+	}
1710
+
1711
+
1712
+	/**
1713
+	 * @throws DomainException
1714
+	 */
1715
+	public function registration_options_meta_box()
1716
+	{
1717
+		$yes_no_values = array(
1718
+			array('id' => true, 'text' => esc_html__('Yes', 'event_espresso')),
1719
+			array('id' => false, 'text' => esc_html__('No', 'event_espresso')),
1720
+		);
1721
+		$default_reg_status_values = EEM_Registration::reg_status_array(
1722
+			array(
1723
+				EEM_Registration::status_id_cancelled,
1724
+				EEM_Registration::status_id_declined,
1725
+				EEM_Registration::status_id_incomplete,
1726
+			),
1727
+			true
1728
+		);
1729
+		// $template_args['is_active_select'] = EEH_Form_Fields::select_input('is_active', $yes_no_values, $this->_cpt_model_obj->is_active());
1730
+		$template_args['_event'] = $this->_cpt_model_obj;
1731
+		$template_args['active_status'] = $this->_cpt_model_obj->pretty_active_status(false);
1732
+		$template_args['additional_limit'] = $this->_cpt_model_obj->additional_limit();
1733
+		$template_args['default_registration_status'] = EEH_Form_Fields::select_input(
1734
+			'default_reg_status',
1735
+			$default_reg_status_values,
1736
+			$this->_cpt_model_obj->default_registration_status()
1737
+		);
1738
+		$template_args['display_description'] = EEH_Form_Fields::select_input(
1739
+			'display_desc',
1740
+			$yes_no_values,
1741
+			$this->_cpt_model_obj->display_description()
1742
+		);
1743
+		$template_args['display_ticket_selector'] = EEH_Form_Fields::select_input(
1744
+			'display_ticket_selector',
1745
+			$yes_no_values,
1746
+			$this->_cpt_model_obj->display_ticket_selector(),
1747
+			'',
1748
+			'',
1749
+			false
1750
+		);
1751
+		$template_args['additional_registration_options'] = apply_filters(
1752
+			'FHEE__Events_Admin_Page__registration_options_meta_box__additional_registration_options',
1753
+			'',
1754
+			$template_args,
1755
+			$yes_no_values,
1756
+			$default_reg_status_values
1757
+		);
1758
+		EEH_Template::display_template(
1759
+			EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1760
+			$template_args
1761
+		);
1762
+	}
1763
+
1764
+
1765
+	/**
1766
+	 * _get_events()
1767
+	 * This method simply returns all the events (for the given _view and paging)
1768
+	 *
1769
+	 * @access public
1770
+	 * @param int  $per_page     count of items per page (20 default);
1771
+	 * @param int  $current_page what is the current page being viewed.
1772
+	 * @param bool $count        if TRUE then we just return a count of ALL events matching the given _view.
1773
+	 *                           If FALSE then we return an array of event objects
1774
+	 *                           that match the given _view and paging parameters.
1775
+	 * @return array an array of event objects.
1776
+	 */
1777
+	public function get_events($per_page = 10, $current_page = 1, $count = false)
1778
+	{
1779
+		$EEME = $this->_event_model();
1780
+		$offset = ($current_page - 1) * $per_page;
1781
+		$limit = $count ? null : $offset . ',' . $per_page;
1782
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1783
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1784
+		if (isset($this->_req_data['month_range'])) {
1785
+			$pieces = explode(' ', $this->_req_data['month_range'], 3);
1786
+			// simulate the FIRST day of the month, that fixes issues for months like February
1787
+			// where PHP doesn't know what to assume for date.
1788
+			// @see https://events.codebasehq.com/projects/event-espresso/tickets/10437
1789
+			$month_r = ! empty($pieces[0]) ? date('m', \EEH_DTT_Helper::first_of_month_timestamp($pieces[0])) : '';
1790
+			$year_r = ! empty($pieces[1]) ? $pieces[1] : '';
1791
+		}
1792
+		$where = array();
1793
+		$status = isset($this->_req_data['status']) ? $this->_req_data['status'] : null;
1794
+		// determine what post_status our condition will have for the query.
1795
+		switch ($status) {
1796
+			case 'month':
1797
+			case 'today':
1798
+			case null:
1799
+			case 'all':
1800
+				break;
1801
+			case 'draft':
1802
+				$where['status'] = array('IN', array('draft', 'auto-draft'));
1803
+				break;
1804
+			default:
1805
+				$where['status'] = $status;
1806
+		}
1807
+		// categories?
1808
+		$category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1809
+			? $this->_req_data['EVT_CAT'] : null;
1810
+		if (! empty($category)) {
1811
+			$where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1812
+			$where['Term_Taxonomy.term_id'] = $category;
1813
+		}
1814
+		// date where conditions
1815
+		$start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1816
+		if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1817
+			$DateTime = new DateTime(
1818
+				$year_r . '-' . $month_r . '-01 00:00:00',
1819
+				new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1820
+			);
1821
+			$start = $DateTime->format(implode(' ', $start_formats));
1822
+			$end = $DateTime->setDate(
1823
+				$year_r,
1824
+				$month_r,
1825
+				$DateTime
1826
+					->format('t')
1827
+			)->setTime(23, 59, 59)
1828
+							->format(implode(' ', $start_formats));
1829
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1830
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'today') {
1831
+			$DateTime = new DateTime('now', new DateTimeZone(EEM_Event::instance()->get_timezone()));
1832
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1833
+			$end = $DateTime->setTime(23, 59, 59)->format(implode(' ', $start_formats));
1834
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1835
+		} elseif (isset($this->_req_data['status']) && $this->_req_data['status'] == 'month') {
1836
+			$now = date('Y-m-01');
1837
+			$DateTime = new DateTime($now, new DateTimeZone(EEM_Event::instance()->get_timezone()));
1838
+			$start = $DateTime->setTime(0, 0, 0)->format(implode(' ', $start_formats));
1839
+			$end = $DateTime->setDate(date('Y'), date('m'), $DateTime->format('t'))
1840
+							->setTime(23, 59, 59)
1841
+							->format(implode(' ', $start_formats));
1842
+			$where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1843
+		}
1844
+		if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1845
+			$where['EVT_wp_user'] = get_current_user_id();
1846
+		} else {
1847
+			if (! isset($where['status'])) {
1848
+				if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1849
+					$where['OR'] = array(
1850
+						'status*restrict_private' => array('!=', 'private'),
1851
+						'AND'                     => array(
1852
+							'status*inclusive' => array('=', 'private'),
1853
+							'EVT_wp_user'      => get_current_user_id(),
1854
+						),
1855
+					);
1856
+				}
1857
+			}
1858
+		}
1859
+		if (isset($this->_req_data['EVT_wp_user'])) {
1860
+			if ($this->_req_data['EVT_wp_user'] != get_current_user_id()
1861
+				&& EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')
1862
+			) {
1863
+				$where['EVT_wp_user'] = $this->_req_data['EVT_wp_user'];
1864
+			}
1865
+		}
1866
+		// search query handling
1867
+		if (isset($this->_req_data['s'])) {
1868
+			$search_string = '%' . $this->_req_data['s'] . '%';
1869
+			$where['OR'] = array(
1870
+				'EVT_name'       => array('LIKE', $search_string),
1871
+				'EVT_desc'       => array('LIKE', $search_string),
1872
+				'EVT_short_desc' => array('LIKE', $search_string),
1873
+			);
1874
+		}
1875
+		// filter events by venue.
1876
+		if (isset($this->_req_data['venue']) && ! empty($this->_req_data['venue'])) {
1877
+			$where['Venue.VNU_ID'] = absint($this->_req_data['venue']);
1878
+		}
1879
+		$where = apply_filters('FHEE__Events_Admin_Page__get_events__where', $where, $this->_req_data);
1880
+		$query_params = apply_filters(
1881
+			'FHEE__Events_Admin_Page__get_events__query_params',
1882
+			array(
1883
+				$where,
1884
+				'limit'    => $limit,
1885
+				'order_by' => $orderby,
1886
+				'order'    => $order,
1887
+				'group_by' => 'EVT_ID',
1888
+			),
1889
+			$this->_req_data
1890
+		);
1891
+		// let's first check if we have special requests coming in.
1892
+		if (isset($this->_req_data['active_status'])) {
1893
+			switch ($this->_req_data['active_status']) {
1894
+				case 'upcoming':
1895
+					return $EEME->get_upcoming_events($query_params, $count);
1896
+					break;
1897
+				case 'expired':
1898
+					return $EEME->get_expired_events($query_params, $count);
1899
+					break;
1900
+				case 'active':
1901
+					return $EEME->get_active_events($query_params, $count);
1902
+					break;
1903
+				case 'inactive':
1904
+					return $EEME->get_inactive_events($query_params, $count);
1905
+					break;
1906
+			}
1907
+		}
1908
+
1909
+		$events = $count ? $EEME->count(array($where), 'EVT_ID', true) : $EEME->get_all($query_params);
1910
+		return $events;
1911
+	}
1912
+
1913
+
1914
+	/**
1915
+	 * handling for WordPress CPT actions (trash, restore, delete)
1916
+	 *
1917
+	 * @param string $post_id
1918
+	 */
1919
+	public function trash_cpt_item($post_id)
1920
+	{
1921
+		$this->_req_data['EVT_ID'] = $post_id;
1922
+		$this->_trash_or_restore_event('trash', false);
1923
+	}
1924
+
1925
+
1926
+	/**
1927
+	 * @param string $post_id
1928
+	 */
1929
+	public function restore_cpt_item($post_id)
1930
+	{
1931
+		$this->_req_data['EVT_ID'] = $post_id;
1932
+		$this->_trash_or_restore_event('draft', false);
1933
+	}
1934
+
1935
+
1936
+	/**
1937
+	 * @param string $post_id
1938
+	 */
1939
+	public function delete_cpt_item($post_id)
1940
+	{
1941
+		throw new EE_Error(esc_html__('Please contact Event Espresso support with the details of the steps taken to produce this error.', 'event_espresso'));
1942
+		$this->_req_data['EVT_ID'] = $post_id;
1943
+		$this->_delete_event();
1944
+	}
1945
+
1946
+
1947
+	/**
1948
+	 * _trash_or_restore_event
1949
+	 *
1950
+	 * @access protected
1951
+	 * @param  string $event_status
1952
+	 * @param bool    $redirect_after
1953
+	 */
1954
+	protected function _trash_or_restore_event($event_status = 'trash', $redirect_after = true)
1955
+	{
1956
+		// determine the event id and set to array.
1957
+		$EVT_ID = isset($this->_req_data['EVT_ID']) ? absint($this->_req_data['EVT_ID']) : false;
1958
+		// loop thru events
1959
+		if ($EVT_ID) {
1960
+			// clean status
1961
+			$event_status = sanitize_key($event_status);
1962
+			// grab status
1963
+			if (! empty($event_status)) {
1964
+				$success = $this->_change_event_status($EVT_ID, $event_status);
1965
+			} else {
1966
+				$success = false;
1967
+				$msg = esc_html__(
1968
+					'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
1969
+					'event_espresso'
1970
+				);
1971
+				EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1972
+			}
1973
+		} else {
1974
+			$success = false;
1975
+			$msg = esc_html__(
1976
+				'An error occurred. The event could not be moved to the trash because a valid event ID was not not supplied.',
1977
+				'event_espresso'
1978
+			);
1979
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
1980
+		}
1981
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
1982
+		if ($redirect_after) {
1983
+			$this->_redirect_after_action($success, 'Event', $action, array('action' => 'default'));
1984
+		}
1985
+	}
1986
+
1987
+
1988
+	/**
1989
+	 * _trash_or_restore_events
1990
+	 *
1991
+	 * @access protected
1992
+	 * @param  string $event_status
1993
+	 * @return void
1994
+	 */
1995
+	protected function _trash_or_restore_events($event_status = 'trash')
1996
+	{
1997
+		// clean status
1998
+		$event_status = sanitize_key($event_status);
1999
+		// grab status
2000
+		if (! empty($event_status)) {
2001
+			$success = true;
2002
+			// determine the event id and set to array.
2003
+			$EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
2004
+			// loop thru events
2005
+			foreach ($EVT_IDs as $EVT_ID) {
2006
+				if ($EVT_ID = absint($EVT_ID)) {
2007
+					$results = $this->_change_event_status($EVT_ID, $event_status);
2008
+					$success = $results !== false ? $success : false;
2009
+				} else {
2010
+					$msg = sprintf(
2011
+						esc_html__(
2012
+							'An error occurred. Event #%d could not be moved to the trash because a valid event ID was not not supplied.',
2013
+							'event_espresso'
2014
+						),
2015
+						$EVT_ID
2016
+					);
2017
+					EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2018
+					$success = false;
2019
+				}
2020
+			}
2021
+		} else {
2022
+			$success = false;
2023
+			$msg = esc_html__(
2024
+				'An error occurred. The event could not be moved to the trash because a valid event status was not not supplied.',
2025
+				'event_espresso'
2026
+			);
2027
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2028
+		}
2029
+		// in order to force a pluralized result message we need to send back a success status greater than 1
2030
+		$success = $success ? 2 : false;
2031
+		$action = $event_status == 'trash' ? 'moved to the trash' : 'restored from the trash';
2032
+		$this->_redirect_after_action($success, 'Events', $action, array('action' => 'default'));
2033
+	}
2034
+
2035
+
2036
+	/**
2037
+	 * _trash_or_restore_events
2038
+	 *
2039
+	 * @access  private
2040
+	 * @param  int    $EVT_ID
2041
+	 * @param  string $event_status
2042
+	 * @return bool
2043
+	 */
2044
+	private function _change_event_status($EVT_ID = 0, $event_status = '')
2045
+	{
2046
+		// grab event id
2047
+		if (! $EVT_ID) {
2048
+			$msg = esc_html__(
2049
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2050
+				'event_espresso'
2051
+			);
2052
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2053
+			return false;
2054
+		}
2055
+		$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2056
+		// clean status
2057
+		$event_status = sanitize_key($event_status);
2058
+		// grab status
2059
+		if (empty($event_status)) {
2060
+			$msg = esc_html__(
2061
+				'An error occurred. No Event Status or an invalid Event Status was received.',
2062
+				'event_espresso'
2063
+			);
2064
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2065
+			return false;
2066
+		}
2067
+		// was event trashed or restored ?
2068
+		switch ($event_status) {
2069
+			case 'draft':
2070
+				$action = 'restored from the trash';
2071
+				$hook = 'AHEE_event_restored_from_trash';
2072
+				break;
2073
+			case 'trash':
2074
+				$action = 'moved to the trash';
2075
+				$hook = 'AHEE_event_moved_to_trash';
2076
+				break;
2077
+			default:
2078
+				$action = 'updated';
2079
+				$hook = false;
2080
+		}
2081
+		// use class to change status
2082
+		$this->_cpt_model_obj->set_status($event_status);
2083
+		$success = $this->_cpt_model_obj->save();
2084
+		if ($success === false) {
2085
+			$msg = sprintf(esc_html__('An error occurred. The event could not be %s.', 'event_espresso'), $action);
2086
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2087
+			return false;
2088
+		}
2089
+		if ($hook) {
2090
+			do_action($hook);
2091
+		}
2092
+		return true;
2093
+	}
2094
+
2095
+
2096
+	/**
2097
+	 * _delete_event
2098
+	 *
2099
+	 * @access protected
2100
+	 * @param bool $redirect_after
2101
+	 */
2102
+	protected function _delete_event()
2103
+	{
2104
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_ID']) ? $this->_req_data['EVT_ID'] : array());
2105
+	}
2106
+
2107
+
2108
+	/**
2109
+	 * _delete_events
2110
+	 *
2111
+	 * @access protected
2112
+	 * @return void
2113
+	 */
2114
+	protected function _delete_events()
2115
+	{
2116
+		$this->generateDeletionPreview(isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array());
2117
+	}
2118
+
2119
+	protected function generateDeletionPreview($event_ids)
2120
+	{
2121
+		$event_ids = (array) $event_ids;
2122
+		// Set a code we can use to reference this deletion task in the batch jobs and preview page.
2123
+		$deletion_job_code = wp_generate_password(6, false);
2124
+		$return_url = EE_Admin_Page::add_query_args_and_nonce(
2125
+			[
2126
+				'action' => 'preview_deletion',
2127
+				'deletion_job_code' => $deletion_job_code,
2128
+			],
2129
+			$this->_admin_base_url
2130
+		);
2131
+		foreach ($event_ids as $EVT_ID) {
2132
+			$event_ids = (int) $EVT_ID;
2133
+		}
2134
+
2135
+		EEH_URL::safeRedirectAndExit(
2136
+			EE_Admin_Page::add_query_args_and_nonce(
2137
+				array(
2138
+					'page'        => 'espresso_batch',
2139
+					'batch'       => EED_Batch::batch_job,
2140
+					'EVT_IDs[]'      => $event_ids,
2141
+					'deletion_job_code' => $deletion_job_code,
2142
+					'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\PreviewEventDeletion'),
2143
+					'return_url'  => urlencode($return_url),
2144
+				),
2145
+				admin_url()
2146
+			)
2147
+		);
2148
+	}
2149
+
2150
+	/**
2151
+	 * Checks for a POST submission
2152
+	 * @since $VID:$
2153
+	 */
2154
+	protected function confirmDeletion()
2155
+	{
2156
+		$deletion_job_code = isset($this->_req_data['deletion_job_code']) ? $this->_req_data['deletion_job_code'] : '';
2157
+		$this->models_and_ids_to_delete = $this->getModelsAndIdsToDelete($deletion_job_code);
2158
+		$this->form = new ConfirmEventDeletionForm($this->models_and_ids_to_delete['Event']);
2159
+		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2160
+			// Initialize the form from the request, and check if its valid.
2161
+			$this->form->receive_form_submission($this->_req_data);
2162
+			if($this->form->is_valid()){
2163
+				// Redirect the user to the deletion batch job.
2164
+				EEH_URL::safeRedirectAndExit(
2165
+					EE_Admin_Page::add_query_args_and_nonce(
2166
+						array(
2167
+							'page'        => 'espresso_batch',
2168
+							'batch'       => EED_Batch::batch_job,
2169
+							'deletion_job_code' => $deletion_job_code,
2170
+							'job_handler' => urlencode('EventEspressoBatchRequest\JobHandlers\ExecuteBatchDeletion'),
2171
+							'return_url'  => urlencode(
2172
+								add_query_arg(
2173
+									[
2174
+										'status' => 'trash'
2175
+									],
2176
+									EVENTS_ADMIN_URL
2177
+								)
2178
+							)
2179
+						),
2180
+						admin_url()
2181
+					)
2182
+				);
2183
+			} else {
2184
+				EE_Error::add_error(
2185
+					__(
2186
+						'Data was not deleted because you did not complete the form correctly.',
2187
+						'event_espresso'
2188
+					),
2189
+					__FILE__,
2190
+					__FUNCTION__,
2191
+					__LINE__
2192
+				);
2193
+			}
2194
+		}
2195
+	}
2196
+
2197
+	/**
2198
+	 * Uses the querystring and job option to figure out what we intend to delete.
2199
+	 * @since $VID:$
2200
+	 * @return array top-level keys are model names, and their values are arrays of IDs.
2201
+	 * @throws EE_Error
2202
+	 * @throws InvalidArgumentException
2203
+	 * @throws InvalidDataTypeException
2204
+	 * @throws InvalidInterfaceException
2205
+	 * @throws ReflectionException
2206
+	 * @throws UnexpectedEntityException
2207
+	 */
2208
+	protected function getModelsAndIdsToDelete($deletion_job_code)
2209
+	{
2210
+		if( ! $deletion_job_code){
2211
+			throw new Exception(esc_html__('We aren’t sure which job you are performing. Please press back in your browser and try again.', 'event_espresso'));
2212
+		}
2213
+		$deletion_data = get_option('ee_deletion_' . $deletion_job_code, []);
2214
+
2215
+		$models_and_ids_to_delete = [];
2216
+		foreach ($deletion_data as $root) {
2217
+			if (! $root instanceof ModelObjNode) {
2218
+				throw new UnexpectedEntityException($root, 'ModelObjNode');
2219
+			}
2220
+			$models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
2221
+		}
2222
+		return $models_and_ids_to_delete;
2223
+	}
2224
+
2225
+	/**
2226
+	 * A page for users to preview what exactly will be deleted, and confirm they want to delete it.
2227
+	 * @since $VID:$
2228
+	 */
2229
+	protected function previewDeletion()
2230
+	{
2231
+		$deletion_job_code = isset($this->_req_data['deletion_job_code']) ? $this->_req_data['deletion_job_code'] : '';
2232
+		if(! $this->form instanceof ConfirmEventDeletionForm){
2233
+			$this->models_and_ids_to_delete = $this->getModelsAndIdsToDelete($deletion_job_code);
2234
+			$this->form = new ConfirmEventDeletionForm($this->models_and_ids_to_delete['Event']);
2235
+		}
2236
+		// If they're not in debug mode, don't list all model objectss that will be deleted. They'll just be confused.
2237
+		if(! WP_DEBUG){
2238
+			$models_to_mention = [
2239
+				'Event',
2240
+				'Datetime',
2241
+				'Ticket',
2242
+				'Registration'
2243
+			];
2244
+
2245
+			$this->models_and_ids_to_delete = array_intersect_key($this->models_and_ids_to_delete, array_flip($models_to_mention));
2246
+		};
2247
+		$confirm_deletion_args = [
2248
+			'action' => 'confirm_deletion',
2249
+			'deletion_job_code' => $deletion_job_code
2250
+		];
2251
+
2252
+		$this->_template_args['admin_page_content'] = EEH_Template::display_template(
2253
+			EVENTS_TEMPLATE_PATH . 'event_preview_deletion.template.php',
2254
+			[
2255
+				'form_url' => EE_Admin_Page::add_query_args_and_nonce(
2256
+					$confirm_deletion_args,
2257
+					$this->admin_base_url()
2258
+				),
2259
+				'form' => $this->form,
2260
+				'models_and_ids_to_delete' => $this->models_and_ids_to_delete,
2261
+				'quantity_to_preview' => 20
2262
+			],
2263
+			true
2264
+		);
2265
+		$this->display_admin_page_with_no_sidebar();
2266
+	}
2267
+
2268
+	/**
2269
+	 * _permanently_delete_event
2270
+	 *
2271
+	 * @access  private
2272
+	 * @param  int $EVT_ID
2273
+	 * @return bool
2274
+	 */
2275
+	private function _permanently_delete_event($EVT_ID = 0)
2276
+	{
2277
+		// grab event id
2278
+		if (! $EVT_ID) {
2279
+			$msg = esc_html__(
2280
+				'An error occurred. No Event ID or an invalid Event ID was received.',
2281
+				'event_espresso'
2282
+			);
2283
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2284
+			return false;
2285
+		}
2286
+		if (! $this->_cpt_model_obj instanceof EE_Event
2287
+			|| $this->_cpt_model_obj->ID() !== $EVT_ID
2288
+		) {
2289
+			$this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2290
+		}
2291
+		if (! $this->_cpt_model_obj instanceof EE_Event) {
2292
+			return false;
2293
+		}
2294
+		// need to delete related tickets and prices first.
2295
+		$datetimes = $this->_cpt_model_obj->get_many_related('Datetime');
2296
+		foreach ($datetimes as $datetime) {
2297
+			$this->_cpt_model_obj->_remove_relation_to($datetime, 'Datetime');
2298
+			$tickets = $datetime->get_many_related('Ticket');
2299
+			foreach ($tickets as $ticket) {
2300
+				$ticket->_remove_relation_to($datetime, 'Datetime');
2301
+				$ticket->delete_related_permanently('Price');
2302
+				$ticket->delete_permanently();
2303
+			}
2304
+			$datetime->delete();
2305
+		}
2306
+		// what about related venues or terms?
2307
+		$venues = $this->_cpt_model_obj->get_many_related('Venue');
2308
+		foreach ($venues as $venue) {
2309
+			$this->_cpt_model_obj->_remove_relation_to($venue, 'Venue');
2310
+		}
2311
+		// any attached question groups?
2312
+		$question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2313
+		if (! empty($question_groups)) {
2314
+			foreach ($question_groups as $question_group) {
2315
+				$this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2316
+			}
2317
+		}
2318
+		// Message Template Groups
2319
+		$this->_cpt_model_obj->_remove_relations('Message_Template_Group');
2320
+		/** @type EE_Term_Taxonomy[] $term_taxonomies */
2321
+		$term_taxonomies = $this->_cpt_model_obj->term_taxonomies();
2322
+		foreach ($term_taxonomies as $term_taxonomy) {
2323
+			$this->_cpt_model_obj->remove_relation_to_term_taxonomy($term_taxonomy);
2324
+		}
2325
+		$success = $this->_cpt_model_obj->delete_permanently();
2326
+		// did it all go as planned ?
2327
+		if ($success) {
2328
+			$msg = sprintf(esc_html__('Event ID # %d has been deleted.', 'event_espresso'), $EVT_ID);
2329
+			EE_Error::add_success($msg);
2330
+		} else {
2331
+			$msg = sprintf(
2332
+				esc_html__('An error occurred. Event ID # %d could not be deleted.', 'event_espresso'),
2333
+				$EVT_ID
2334
+			);
2335
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2336
+			return false;
2337
+		}
2338
+		do_action('AHEE__Events_Admin_Page___permanently_delete_event__after_event_deleted', $EVT_ID);
2339
+		return true;
2340
+	}
2341
+
2342
+
2343
+	/**
2344
+	 * get total number of events
2345
+	 *
2346
+	 * @access public
2347
+	 * @return int
2348
+	 */
2349
+	public function total_events()
2350
+	{
2351
+		$count = EEM_Event::instance()->count(array('caps' => 'read_admin'), 'EVT_ID', true);
2352
+		return $count;
2353
+	}
2354
+
2355
+
2356
+	/**
2357
+	 * get total number of draft events
2358
+	 *
2359
+	 * @access public
2360
+	 * @return int
2361
+	 */
2362
+	public function total_events_draft()
2363
+	{
2364
+		$where = array(
2365
+			'status' => array('IN', array('draft', 'auto-draft')),
2366
+		);
2367
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2368
+		return $count;
2369
+	}
2370
+
2371
+
2372
+	/**
2373
+	 * get total number of trashed events
2374
+	 *
2375
+	 * @access public
2376
+	 * @return int
2377
+	 */
2378
+	public function total_trashed_events()
2379
+	{
2380
+		$where = array(
2381
+			'status' => 'trash',
2382
+		);
2383
+		$count = EEM_Event::instance()->count(array($where, 'caps' => 'read_admin'), 'EVT_ID', true);
2384
+		return $count;
2385
+	}
2386
+
2387
+
2388
+	/**
2389
+	 *    _default_event_settings
2390
+	 *    This generates the Default Settings Tab
2391
+	 *
2392
+	 * @return void
2393
+	 * @throws EE_Error
2394
+	 */
2395
+	protected function _default_event_settings()
2396
+	{
2397
+		$this->_set_add_edit_form_tags('update_default_event_settings');
2398
+		$this->_set_publish_post_box_vars(null, false, false, null, false);
2399
+		$this->_template_args['admin_page_content'] = $this->_default_event_settings_form()->get_html();
2400
+		$this->display_admin_page_with_sidebar();
2401
+	}
2402
+
2403
+
2404
+	/**
2405
+	 * Return the form for event settings.
2406
+	 *
2407
+	 * @return EE_Form_Section_Proper
2408
+	 * @throws EE_Error
2409
+	 */
2410
+	protected function _default_event_settings_form()
2411
+	{
2412
+		$registration_config = EE_Registry::instance()->CFG->registration;
2413
+		$registration_stati_for_selection = EEM_Registration::reg_status_array(
2414
+			// exclude
2415
+			array(
2416
+				EEM_Registration::status_id_cancelled,
2417
+				EEM_Registration::status_id_declined,
2418
+				EEM_Registration::status_id_incomplete,
2419
+				EEM_Registration::status_id_wait_list,
2420
+			),
2421
+			true
2422
+		);
2423
+		return new EE_Form_Section_Proper(
2424
+			array(
2425
+				'name'            => 'update_default_event_settings',
2426
+				'html_id'         => 'update_default_event_settings',
2427
+				'html_class'      => 'form-table',
2428
+				'layout_strategy' => new EE_Admin_Two_Column_Layout(),
2429
+				'subsections'     => apply_filters(
2430
+					'FHEE__Events_Admin_Page___default_event_settings_form__form_subsections',
2431
+					array(
2432
+						'default_reg_status'  => new EE_Select_Input(
2433
+							$registration_stati_for_selection,
2434
+							array(
2435
+								'default'         => isset($registration_config->default_STS_ID)
2436
+													 && array_key_exists(
2437
+														 $registration_config->default_STS_ID,
2438
+														 $registration_stati_for_selection
2439
+													 )
2440
+									? sanitize_text_field($registration_config->default_STS_ID)
2441
+									: EEM_Registration::status_id_pending_payment,
2442
+								'html_label_text' => esc_html__('Default Registration Status', 'event_espresso')
2443
+													 . EEH_Template::get_help_tab_link(
2444
+														 'default_settings_status_help_tab'
2445
+													 ),
2446
+								'html_help_text'  => esc_html__(
2447
+									'This setting allows you to preselect what the default registration status setting is when creating an event.  Note that changing this setting does NOT retroactively apply it to existing events.',
2448
+									'event_espresso'
2449
+								),
2450
+							)
2451
+						),
2452
+						'default_max_tickets' => new EE_Integer_Input(
2453
+							array(
2454
+								'default'         => isset($registration_config->default_maximum_number_of_tickets)
2455
+									? $registration_config->default_maximum_number_of_tickets
2456
+									: EEM_Event::get_default_additional_limit(),
2457
+								'html_label_text' => esc_html__(
2458
+									'Default Maximum Tickets Allowed Per Order:',
2459
+									'event_espresso'
2460
+								)
2461
+													 . EEH_Template::get_help_tab_link(
2462
+														 'default_maximum_tickets_help_tab"'
2463
+													 ),
2464
+								'html_help_text'  => esc_html__(
2465
+									'This setting allows you to indicate what will be the default for the maximum number of tickets per order when creating new events.',
2466
+									'event_espresso'
2467
+								),
2468
+							)
2469
+						),
2470
+					)
2471
+				),
2472
+			)
2473
+		);
2474
+	}
2475
+
2476
+
2477
+	/**
2478
+	 * _update_default_event_settings
2479
+	 *
2480
+	 * @access protected
2481
+	 * @return void
2482
+	 * @throws EE_Error
2483
+	 */
2484
+	protected function _update_default_event_settings()
2485
+	{
2486
+		$registration_config = EE_Registry::instance()->CFG->registration;
2487
+		$form = $this->_default_event_settings_form();
2488
+		if ($form->was_submitted()) {
2489
+			$form->receive_form_submission();
2490
+			if ($form->is_valid()) {
2491
+				$valid_data = $form->valid_data();
2492
+				if (isset($valid_data['default_reg_status'])) {
2493
+					$registration_config->default_STS_ID = $valid_data['default_reg_status'];
2494
+				}
2495
+				if (isset($valid_data['default_max_tickets'])) {
2496
+					$registration_config->default_maximum_number_of_tickets = $valid_data['default_max_tickets'];
2497
+				}
2498
+				// update because data was valid!
2499
+				EE_Registry::instance()->CFG->update_espresso_config();
2500
+				EE_Error::overwrite_success();
2501
+				EE_Error::add_success(
2502
+					__('Default Event Settings were updated', 'event_espresso')
2503
+				);
2504
+			}
2505
+		}
2506
+		$this->_redirect_after_action(0, '', '', array('action' => 'default_event_settings'), true);
2507
+	}
2508
+
2509
+
2510
+	/*************        Templates        *************/
2511
+	protected function _template_settings()
2512
+	{
2513
+		$this->_admin_page_title = esc_html__('Template Settings (Preview)', 'event_espresso');
2514
+		$this->_template_args['preview_img'] = '<img src="'
2515
+											   . EVENTS_ASSETS_URL
2516
+											   . '/images/'
2517
+											   . 'caffeinated_template_features.jpg" alt="'
2518
+											   . esc_attr__('Template Settings Preview screenshot', 'event_espresso')
2519
+											   . '" />';
2520
+		$this->_template_args['preview_text'] = '<strong>'
2521
+												. esc_html__(
2522
+													'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2523
+													'event_espresso'
2524
+												) . '</strong>';
2525
+		$this->display_admin_caf_preview_page('template_settings_tab');
2526
+	}
2527
+
2528
+
2529
+	/** Event Category Stuff **/
2530
+	/**
2531
+	 * set the _category property with the category object for the loaded page.
2532
+	 *
2533
+	 * @access private
2534
+	 * @return void
2535
+	 */
2536
+	private function _set_category_object()
2537
+	{
2538
+		if (isset($this->_category->id) && ! empty($this->_category->id)) {
2539
+			return;
2540
+		} //already have the category object so get out.
2541
+		// set default category object
2542
+		$this->_set_empty_category_object();
2543
+		// only set if we've got an id
2544
+		if (! isset($this->_req_data['EVT_CAT_ID'])) {
2545
+			return;
2546
+		}
2547
+		$category_id = absint($this->_req_data['EVT_CAT_ID']);
2548
+		$term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2549
+		if (! empty($term)) {
2550
+			$this->_category->category_name = $term->name;
2551
+			$this->_category->category_identifier = $term->slug;
2552
+			$this->_category->category_desc = $term->description;
2553
+			$this->_category->id = $term->term_id;
2554
+			$this->_category->parent = $term->parent;
2555
+		}
2556
+	}
2557
+
2558
+
2559
+	/**
2560
+	 * Clears out category properties.
2561
+	 */
2562
+	private function _set_empty_category_object()
2563
+	{
2564
+		$this->_category = new stdClass();
2565
+		$this->_category->category_name = $this->_category->category_identifier = $this->_category->category_desc = '';
2566
+		$this->_category->id = $this->_category->parent = 0;
2567
+	}
2568
+
2569
+
2570
+	/**
2571
+	 * @throws EE_Error
2572
+	 */
2573
+	protected function _category_list_table()
2574
+	{
2575
+		do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2576
+		$this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2577
+		$this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2578
+			'add_category',
2579
+			'add_category',
2580
+			array(),
2581
+			'add-new-h2'
2582
+		);
2583
+		$this->display_admin_list_table_page_with_sidebar();
2584
+	}
2585
+
2586
+
2587
+	/**
2588
+	 * Output category details view.
2589
+	 */
2590
+	protected function _category_details($view)
2591
+	{
2592
+		// load formatter helper
2593
+		// load field generator helper
2594
+		$route = $view == 'edit' ? 'update_category' : 'insert_category';
2595
+		$this->_set_add_edit_form_tags($route);
2596
+		$this->_set_category_object();
2597
+		$id = ! empty($this->_category->id) ? $this->_category->id : '';
2598
+		$delete_action = 'delete_category';
2599
+		// custom redirect
2600
+		$redirect = EE_Admin_Page::add_query_args_and_nonce(
2601
+			array('action' => 'category_list'),
2602
+			$this->_admin_base_url
2603
+		);
2604
+		$this->_set_publish_post_box_vars('EVT_CAT_ID', $id, $delete_action, $redirect);
2605
+		// take care of contents
2606
+		$this->_template_args['admin_page_content'] = $this->_category_details_content();
2607
+		$this->display_admin_page_with_sidebar();
2608
+	}
2609
+
2610
+
2611
+	/**
2612
+	 * Output category details content.
2613
+	 */
2614
+	protected function _category_details_content()
2615
+	{
2616
+		$editor_args['category_desc'] = array(
2617
+			'type'          => 'wp_editor',
2618
+			'value'         => EEH_Formatter::admin_format_content($this->_category->category_desc),
2619
+			'class'         => 'my_editor_custom',
2620
+			'wpeditor_args' => array('media_buttons' => false),
2621
+		);
2622
+		$_wp_editor = $this->_generate_admin_form_fields($editor_args, 'array');
2623
+		$all_terms = get_terms(
2624
+			array(EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY),
2625
+			array('hide_empty' => 0, 'exclude' => array($this->_category->id))
2626
+		);
2627
+		// setup category select for term parents.
2628
+		$category_select_values[] = array(
2629
+			'text' => esc_html__('No Parent', 'event_espresso'),
2630
+			'id'   => 0,
2631
+		);
2632
+		foreach ($all_terms as $term) {
2633
+			$category_select_values[] = array(
2634
+				'text' => $term->name,
2635
+				'id'   => $term->term_id,
2636
+			);
2637
+		}
2638
+		$category_select = EEH_Form_Fields::select_input(
2639
+			'category_parent',
2640
+			$category_select_values,
2641
+			$this->_category->parent
2642
+		);
2643
+		$template_args = array(
2644
+			'category'                 => $this->_category,
2645
+			'category_select'          => $category_select,
2646
+			'unique_id_info_help_link' => $this->_get_help_tab_link('unique_id_info'),
2647
+			'category_desc_editor'     => $_wp_editor['category_desc']['field'],
2648
+			'disable'                  => '',
2649
+			'disabled_message'         => false,
2650
+		);
2651
+		$template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2652
+		return EEH_Template::display_template($template, $template_args, true);
2653
+	}
2654
+
2655
+
2656
+	/**
2657
+	 * Handles deleting categories.
2658
+	 */
2659
+	protected function _delete_categories()
2660
+	{
2661
+		$cat_ids = isset($this->_req_data['EVT_CAT_ID']) ? (array) $this->_req_data['EVT_CAT_ID']
2662
+			: (array) $this->_req_data['category_id'];
2663
+		foreach ($cat_ids as $cat_id) {
2664
+			$this->_delete_category($cat_id);
2665
+		}
2666
+		// doesn't matter what page we're coming from... we're going to the same place after delete.
2667
+		$query_args = array(
2668
+			'action' => 'category_list',
2669
+		);
2670
+		$this->_redirect_after_action(0, '', '', $query_args);
2671
+	}
2672
+
2673
+
2674
+	/**
2675
+	 * Handles deleting specific category.
2676
+	 *
2677
+	 * @param int $cat_id
2678
+	 */
2679
+	protected function _delete_category($cat_id)
2680
+	{
2681
+		$cat_id = absint($cat_id);
2682
+		wp_delete_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2683
+	}
2684
+
2685
+
2686
+	/**
2687
+	 * Handles triggering the update or insertion of a new category.
2688
+	 *
2689
+	 * @param bool $new_category true means we're triggering the insert of a new category.
2690
+	 */
2691
+	protected function _insert_or_update_category($new_category)
2692
+	{
2693
+		$cat_id = $new_category ? $this->_insert_category() : $this->_insert_category(true);
2694
+		$success = 0; // we already have a success message so lets not send another.
2695
+		if ($cat_id) {
2696
+			$query_args = array(
2697
+				'action'     => 'edit_category',
2698
+				'EVT_CAT_ID' => $cat_id,
2699
+			);
2700
+		} else {
2701
+			$query_args = array('action' => 'add_category');
2702
+		}
2703
+		$this->_redirect_after_action($success, '', '', $query_args, true);
2704
+	}
2705
+
2706
+
2707
+	/**
2708
+	 * Inserts or updates category
2709
+	 *
2710
+	 * @param bool $update (true indicates we're updating a category).
2711
+	 * @return bool|mixed|string
2712
+	 */
2713
+	private function _insert_category($update = false)
2714
+	{
2715
+		$cat_id = $update ? $this->_req_data['EVT_CAT_ID'] : '';
2716
+		$category_name = isset($this->_req_data['category_name']) ? $this->_req_data['category_name'] : '';
2717
+		$category_desc = isset($this->_req_data['category_desc']) ? $this->_req_data['category_desc'] : '';
2718
+		$category_parent = isset($this->_req_data['category_parent']) ? $this->_req_data['category_parent'] : 0;
2719
+		if (empty($category_name)) {
2720
+			$msg = esc_html__('You must add a name for the category.', 'event_espresso');
2721
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2722
+			return false;
2723
+		}
2724
+		$term_args = array(
2725
+			'name'        => $category_name,
2726
+			'description' => $category_desc,
2727
+			'parent'      => $category_parent,
2728
+		);
2729
+		// was the category_identifier input disabled?
2730
+		if (isset($this->_req_data['category_identifier'])) {
2731
+			$term_args['slug'] = $this->_req_data['category_identifier'];
2732
+		}
2733
+		$insert_ids = $update
2734
+			? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2735
+			: wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2736
+		if (! is_array($insert_ids)) {
2737
+			$msg = esc_html__(
2738
+				'An error occurred and the category has not been saved to the database.',
2739
+				'event_espresso'
2740
+			);
2741
+			EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2742
+		} else {
2743
+			$cat_id = $insert_ids['term_id'];
2744
+			$msg = sprintf(esc_html__('The category %s was successfully saved', 'event_espresso'), $category_name);
2745
+			EE_Error::add_success($msg);
2746
+		}
2747
+		return $cat_id;
2748
+	}
2749
+
2750
+
2751
+	/**
2752
+	 * Gets categories or count of categories matching the arguments in the request.
2753
+	 *
2754
+	 * @param int  $per_page
2755
+	 * @param int  $current_page
2756
+	 * @param bool $count
2757
+	 * @return EE_Base_Class[]|EE_Term_Taxonomy[]|int
2758
+	 */
2759
+	public function get_categories($per_page = 10, $current_page = 1, $count = false)
2760
+	{
2761
+		// testing term stuff
2762
+		$orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'Term.term_id';
2763
+		$order = isset($this->_req_data['order']) ? $this->_req_data['order'] : 'DESC';
2764
+		$limit = ($current_page - 1) * $per_page;
2765
+		$where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2766
+		if (isset($this->_req_data['s'])) {
2767
+			$sstr = '%' . $this->_req_data['s'] . '%';
2768
+			$where['OR'] = array(
2769
+				'Term.name'   => array('LIKE', $sstr),
2770
+				'description' => array('LIKE', $sstr),
2771
+			);
2772
+		}
2773
+		$query_params = array(
2774
+			$where,
2775
+			'order_by'   => array($orderby => $order),
2776
+			'limit'      => $limit . ',' . $per_page,
2777
+			'force_join' => array('Term'),
2778
+		);
2779
+		$categories = $count
2780
+			? EEM_Term_Taxonomy::instance()->count($query_params, 'term_id')
2781
+			: EEM_Term_Taxonomy::instance()->get_all($query_params);
2782
+		return $categories;
2783
+	}
2784
+
2785
+	/* end category stuff */
2786
+	/**************/
2787
+
2788
+
2789
+	/**
2790
+	 * Callback for the `ee_save_timezone_setting` ajax action.
2791
+	 *
2792
+	 * @throws EE_Error
2793
+	 */
2794
+	public function save_timezonestring_setting()
2795
+	{
2796
+		$timezone_string = isset($this->_req_data['timezone_selected'])
2797
+			? $this->_req_data['timezone_selected']
2798
+			: '';
2799
+		if (empty($timezone_string) || ! EEH_DTT_Helper::validate_timezone($timezone_string, false)) {
2800
+			EE_Error::add_error(
2801
+				esc_html__('An invalid timezone string submitted.', 'event_espresso'),
2802
+				__FILE__,
2803
+				__FUNCTION__,
2804
+				__LINE__
2805
+			);
2806
+			$this->_template_args['error'] = true;
2807
+			$this->_return_json();
2808
+		}
2809
+
2810
+		update_option('timezone_string', $timezone_string);
2811
+		EE_Error::add_success(
2812
+			esc_html__('Your timezone string was updated.', 'event_espresso')
2813
+		);
2814
+		$this->_template_args['success'] = true;
2815
+		$this->_return_json(true, array('action' => 'create_new'));
2816
+	}
2817 2817
 }
Please login to merge, or discard this patch.
Spacing   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -584,11 +584,11 @@  discard block
 block discarded – undo
584 584
     {
585 585
         wp_register_style(
586 586
             'events-admin-css',
587
-            EVENTS_ASSETS_URL . 'events-admin-page.css',
587
+            EVENTS_ASSETS_URL.'events-admin-page.css',
588 588
             array(),
589 589
             EVENT_ESPRESSO_VERSION
590 590
         );
591
-        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL . 'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
591
+        wp_register_style('ee-cat-admin', EVENTS_ASSETS_URL.'ee-cat-admin.css', array(), EVENT_ESPRESSO_VERSION);
592 592
         wp_enqueue_style('events-admin-css');
593 593
         wp_enqueue_style('ee-cat-admin');
594 594
         // todo note: we also need to load_scripts_styles per view (i.e. default/view_report/event_details
@@ -596,7 +596,7 @@  discard block
 block discarded – undo
596 596
         // scripts
597 597
         wp_register_script(
598 598
             'event_editor_js',
599
-            EVENTS_ASSETS_URL . 'event_editor.js',
599
+            EVENTS_ASSETS_URL.'event_editor.js',
600 600
             array('ee_admin_js', 'jquery-ui-slider', 'jquery-ui-timepicker-addon'),
601 601
             EVENT_ESPRESSO_VERSION,
602 602
             true
@@ -622,7 +622,7 @@  discard block
 block discarded – undo
622 622
         wp_enqueue_style('espresso-ui-theme');
623 623
         wp_register_style(
624 624
             'event-editor-css',
625
-            EVENTS_ASSETS_URL . 'event-editor.css',
625
+            EVENTS_ASSETS_URL.'event-editor.css',
626 626
             array('ee-admin-css'),
627 627
             EVENT_ESPRESSO_VERSION
628 628
         );
@@ -630,7 +630,7 @@  discard block
 block discarded – undo
630 630
         // scripts
631 631
         wp_register_script(
632 632
             'event-datetime-metabox',
633
-            EVENTS_ASSETS_URL . 'event-datetime-metabox.js',
633
+            EVENTS_ASSETS_URL.'event-datetime-metabox.js',
634 634
             array('event_editor_js', 'ee-datepicker'),
635 635
             EVENT_ESPRESSO_VERSION
636 636
         );
@@ -699,7 +699,7 @@  discard block
 block discarded – undo
699 699
     public function verify_event_edit($event = null, $req_type = '')
700 700
     {
701 701
         // don't need to do this when processing
702
-        if (! empty($req_type)) {
702
+        if ( ! empty($req_type)) {
703 703
             return;
704 704
         }
705 705
         // no event?
@@ -708,7 +708,7 @@  discard block
 block discarded – undo
708 708
             $event = $this->_cpt_model_obj;
709 709
         }
710 710
         // STILL no event?
711
-        if (! $event instanceof EE_Event) {
711
+        if ( ! $event instanceof EE_Event) {
712 712
             return;
713 713
         }
714 714
         $orig_status = $event->status();
@@ -746,7 +746,7 @@  discard block
 block discarded – undo
746 746
             );
747 747
         }
748 748
         // now we need to determine if the event has any tickets on sale.  If not then we dont' show the error
749
-        if (! $event->tickets_on_sale()) {
749
+        if ( ! $event->tickets_on_sale()) {
750 750
             return;
751 751
         }
752 752
         // made it here so show warning
@@ -791,7 +791,7 @@  discard block
 block discarded – undo
791 791
     {
792 792
         $has_timezone_string = get_option('timezone_string');
793 793
         // only nag them about setting their timezone if it's their first event, and they haven't already done it
794
-        if (! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
794
+        if ( ! $has_timezone_string && ! EEM_Event::instance()->exists(array())) {
795 795
             EE_Error::add_attention(
796 796
                 sprintf(
797 797
                     __(
@@ -875,31 +875,31 @@  discard block
 block discarded – undo
875 875
         $items = apply_filters('FHEE__Events_Admin_Page___event_legend_items__items', $items);
876 876
         $statuses = array(
877 877
             'sold_out_status'  => array(
878
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::sold_out,
878
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::sold_out,
879 879
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::sold_out, false, 'sentence'),
880 880
             ),
881 881
             'active_status'    => array(
882
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::active,
882
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::active,
883 883
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::active, false, 'sentence'),
884 884
             ),
885 885
             'upcoming_status'  => array(
886
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::upcoming,
886
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::upcoming,
887 887
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::upcoming, false, 'sentence'),
888 888
             ),
889 889
             'postponed_status' => array(
890
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::postponed,
890
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::postponed,
891 891
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::postponed, false, 'sentence'),
892 892
             ),
893 893
             'cancelled_status' => array(
894
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::cancelled,
894
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::cancelled,
895 895
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::cancelled, false, 'sentence'),
896 896
             ),
897 897
             'expired_status'   => array(
898
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::expired,
898
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::expired,
899 899
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::expired, false, 'sentence'),
900 900
             ),
901 901
             'inactive_status'  => array(
902
-                'class' => 'ee-status-legend ee-status-legend-' . EE_Datetime::inactive,
902
+                'class' => 'ee-status-legend ee-status-legend-'.EE_Datetime::inactive,
903 903
                 'desc'  => EEH_Template::pretty_status(EE_Datetime::inactive, false, 'sentence'),
904 904
             ),
905 905
         );
@@ -913,7 +913,7 @@  discard block
 block discarded – undo
913 913
      */
914 914
     private function _event_model()
915 915
     {
916
-        if (! $this->_event_model instanceof EEM_Event) {
916
+        if ( ! $this->_event_model instanceof EEM_Event) {
917 917
             $this->_event_model = EE_Registry::instance()->load_model('Event');
918 918
         }
919 919
         return $this->_event_model;
@@ -933,7 +933,7 @@  discard block
 block discarded – undo
933 933
     public function extra_permalink_field_buttons($return, $id, $new_title, $new_slug)
934 934
     {
935 935
         // make sure this is only when editing
936
-        if (! empty($id)) {
936
+        if ( ! empty($id)) {
937 937
             $post = get_post($id);
938 938
             $return .= '<a class="button button-small" onclick="prompt(\'Shortcode:\', jQuery(\'#shortcode\').val()); return false;" href="#"  tabindex="-1">'
939 939
                        . esc_html__('Shortcode', 'event_espresso')
@@ -967,7 +967,7 @@  discard block
 block discarded – undo
967 967
                     'button'
968 968
                 );
969 969
         $this->_template_args['after_list_table']['legend'] = $this->_display_legend($this->_event_legend_items());
970
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
970
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
971 971
             'create_new',
972 972
             'add',
973 973
             array(),
@@ -1107,7 +1107,7 @@  discard block
 block discarded – undo
1107 1107
      */
1108 1108
     protected function _default_venue_update(\EE_Event $evtobj, $data)
1109 1109
     {
1110
-        require_once(EE_MODELS . 'EEM_Venue.model.php');
1110
+        require_once(EE_MODELS.'EEM_Venue.model.php');
1111 1111
         $venue_model = EE_Registry::instance()->load_model('Venue');
1112 1112
         $rows_affected = null;
1113 1113
         $venue_id = ! empty($data['venue_id']) ? $data['venue_id'] : null;
@@ -1138,7 +1138,7 @@  discard block
 block discarded – undo
1138 1138
             'status'              => 'publish',
1139 1139
         );
1140 1140
         // if we've got the venue_id then we're just updating the existing venue so let's do that and then get out.
1141
-        if (! empty($venue_id)) {
1141
+        if ( ! empty($venue_id)) {
1142 1142
             $update_where = array($venue_model->primary_key_name() => $venue_id);
1143 1143
             $rows_affected = $venue_model->update($venue_array, array($update_where));
1144 1144
             // we've gotta make sure that the venue is always attached to a revision.. add_relation_to should take care of making sure that the relation is already present.
@@ -1180,7 +1180,7 @@  discard block
 block discarded – undo
1180 1180
                 'DTT_order'     => $row,
1181 1181
             );
1182 1182
             // if we have an id then let's get existing object first and then set the new values.  Otherwise we instantiate a new object for save.
1183
-            if (! empty($dtt['DTT_ID'])) {
1183
+            if ( ! empty($dtt['DTT_ID'])) {
1184 1184
                 $DTM = EE_Registry::instance()
1185 1185
                                   ->load_model('Datetime', array($evtobj->get_timezone()))
1186 1186
                                   ->get_one_by_ID($dtt['DTT_ID']);
@@ -1190,7 +1190,7 @@  discard block
 block discarded – undo
1190 1190
                     $DTM->set($field, $value);
1191 1191
                 }
1192 1192
                 // make sure the $dtt_id here is saved just in case after the add_relation_to() the autosave replaces it.  We need to do this so we dont' TRASH the parent DTT.
1193
-                $saved_dtts[ $DTM->ID() ] = $DTM;
1193
+                $saved_dtts[$DTM->ID()] = $DTM;
1194 1194
             } else {
1195 1195
                 $DTM = EE_Registry::instance()->load_class(
1196 1196
                     'Datetime',
@@ -1223,14 +1223,14 @@  discard block
 block discarded – undo
1223 1223
         foreach ($data['edit_tickets'] as $row => $tkt) {
1224 1224
             $incoming_date_formats = array('Y-m-d', 'h:i a');
1225 1225
             $update_prices = false;
1226
-            $ticket_price = isset($data['edit_prices'][ $row ][1]['PRC_amount'])
1227
-                ? $data['edit_prices'][ $row ][1]['PRC_amount'] : 0;
1226
+            $ticket_price = isset($data['edit_prices'][$row][1]['PRC_amount'])
1227
+                ? $data['edit_prices'][$row][1]['PRC_amount'] : 0;
1228 1228
             // trim inputs to ensure any excess whitespace is removed.
1229 1229
             $tkt = array_map('trim', $tkt);
1230 1230
             if (empty($tkt['TKT_start_date'])) {
1231 1231
                 // let's use now in the set timezone.
1232 1232
                 $now = new DateTime('now', new DateTimeZone($evtobj->get_timezone()));
1233
-                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0] . ' ' . $incoming_date_formats[1]);
1233
+                $tkt['TKT_start_date'] = $now->format($incoming_date_formats[0].' '.$incoming_date_formats[1]);
1234 1234
             }
1235 1235
             if (empty($tkt['TKT_end_date'])) {
1236 1236
                 // use the start date of the first datetime
@@ -1265,7 +1265,7 @@  discard block
 block discarded – undo
1265 1265
             // if we have a TKT_ID then we need to get that existing TKT_obj and update it
1266 1266
             // we actually do our saves a head of doing any add_relations to because its entirely possible that this ticket didn't removed or added to any datetime in the session but DID have it's items modified.
1267 1267
             // keep in mind that if the TKT has been sold (and we have changed pricing information), then we won't be updating the tkt but instead a new tkt will be created and the old one archived.
1268
-            if (! empty($tkt['TKT_ID'])) {
1268
+            if ( ! empty($tkt['TKT_ID'])) {
1269 1269
                 $TKT = EE_Registry::instance()
1270 1270
                                   ->load_model('Ticket', array($evtobj->get_timezone()))
1271 1271
                                   ->get_one_by_ID($tkt['TKT_ID']);
@@ -1300,7 +1300,7 @@  discard block
 block discarded – undo
1300 1300
                         $TKT->set('TKT_deleted', 1);
1301 1301
                         $TKT->save();
1302 1302
                         // make sure this ticket is still recorded in our saved_tkts so we don't run it through the regular trash routine.
1303
-                        $saved_tickets[ $TKT->ID() ] = $TKT;
1303
+                        $saved_tickets[$TKT->ID()] = $TKT;
1304 1304
                         // create new ticket that's a copy of the existing except a new id of course (and not archived) AND has the new TKT_price associated with it.
1305 1305
                         $TKT = clone $TKT;
1306 1306
                         $TKT->set('TKT_ID', 0);
@@ -1345,9 +1345,9 @@  discard block
 block discarded – undo
1345 1345
             }
1346 1346
             // initially let's add the ticket to the dtt
1347 1347
             $saved_dtt->_add_relation_to($TKT, 'Ticket');
1348
-            $saved_tickets[ $TKT->ID() ] = $TKT;
1348
+            $saved_tickets[$TKT->ID()] = $TKT;
1349 1349
             // add prices to ticket
1350
-            $this->_add_prices_to_ticket($data['edit_prices'][ $row ], $TKT, $update_prices);
1350
+            $this->_add_prices_to_ticket($data['edit_prices'][$row], $TKT, $update_prices);
1351 1351
         }
1352 1352
         // however now we need to handle permanently deleting tickets via the ui.  Keep in mind that the ui does not allow deleting/archiving tickets that have ticket sold.  However, it does allow for deleting tickets that have no tickets sold, in which case we want to get rid of permanently because there is no need to save in db.
1353 1353
         $old_tickets = isset($old_tickets[0]) && $old_tickets[0] == '' ? array() : $old_tickets;
@@ -1504,7 +1504,7 @@  discard block
 block discarded – undo
1504 1504
         $publish_box_extra_args['event_editor_overview_add'] = ob_get_clean();
1505 1505
         // load template
1506 1506
         EEH_Template::display_template(
1507
-            EVENTS_TEMPLATE_PATH . 'event_publish_box_extras.template.php',
1507
+            EVENTS_TEMPLATE_PATH.'event_publish_box_extras.template.php',
1508 1508
             $publish_box_extra_args
1509 1509
         );
1510 1510
     }
@@ -1596,7 +1596,7 @@  discard block
 block discarded – undo
1596 1596
                     'default_where_conditions' => 'none',
1597 1597
                 )
1598 1598
             );
1599
-            if (! empty($related_tickets)) {
1599
+            if ( ! empty($related_tickets)) {
1600 1600
                 $template_args['total_ticket_rows'] = count($related_tickets);
1601 1601
                 $row = 0;
1602 1602
                 foreach ($related_tickets as $ticket) {
@@ -1630,7 +1630,7 @@  discard block
 block discarded – undo
1630 1630
         );
1631 1631
         $template = apply_filters(
1632 1632
             'FHEE__Events_Admin_Page__ticket_metabox__template',
1633
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_main.template.php'
1633
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_main.template.php'
1634 1634
         );
1635 1635
         EEH_Template::display_template($template, $template_args);
1636 1636
     }
@@ -1648,7 +1648,7 @@  discard block
 block discarded – undo
1648 1648
     private function _get_ticket_row($ticket, $skeleton = false, $row = 0)
1649 1649
     {
1650 1650
         $template_args = array(
1651
-            'tkt_status_class'    => ' tkt-status-' . $ticket->ticket_status(),
1651
+            'tkt_status_class'    => ' tkt-status-'.$ticket->ticket_status(),
1652 1652
             'tkt_archive_class'   => $ticket->ticket_status() === EE_Ticket::archived && ! $skeleton ? ' tkt-archived'
1653 1653
                 : '',
1654 1654
             'ticketrow'           => $skeleton ? 'TICKETNUM' : $row,
@@ -1660,10 +1660,10 @@  discard block
 block discarded – undo
1660 1660
             'TKT_qty'             => $ticket->get_pretty('TKT_qty', 'input'),
1661 1661
             'edit_ticketrow_name' => $skeleton ? 'TICKETNAMEATTR' : 'edit_tickets',
1662 1662
             'TKT_sold'            => $skeleton ? 0 : $ticket->get('TKT_sold'),
1663
-            'trash_icon'          => ($skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')))
1664
-                                     && (! empty($ticket) && $ticket->get('TKT_sold') === 0)
1663
+            'trash_icon'          => ($skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')))
1664
+                                     && ( ! empty($ticket) && $ticket->get('TKT_sold') === 0)
1665 1665
                 ? 'trash-icon dashicons dashicons-post-trash clickable' : 'ee-lock-icon',
1666
-            'disabled'            => $skeleton || (! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1666
+            'disabled'            => $skeleton || ( ! empty($ticket) && ! $ticket->get('TKT_deleted')) ? ''
1667 1667
                 : ' disabled=disabled',
1668 1668
         );
1669 1669
         $price = $ticket->ID() !== 0
@@ -1690,7 +1690,7 @@  discard block
 block discarded – undo
1690 1690
                     array('order_by' => array('DTT_EVT_start' => 'ASC'))
1691 1691
                 )
1692 1692
                 : null;
1693
-            if (! empty($earliest_dtt)) {
1693
+            if ( ! empty($earliest_dtt)) {
1694 1694
                 $template_args['TKT_end_date'] = $earliest_dtt->get_datetime('DTT_EVT_start', 'Y-m-d', 'h:i a');
1695 1695
             } else {
1696 1696
                 $template_args['TKT_end_date'] = date(
@@ -1702,7 +1702,7 @@  discard block
 block discarded – undo
1702 1702
         $template_args = array_merge($template_args, $price_args);
1703 1703
         $template = apply_filters(
1704 1704
             'FHEE__Events_Admin_Page__get_ticket_row__template',
1705
-            EVENTS_TEMPLATE_PATH . 'event_tickets_metabox_ticket_row.template.php',
1705
+            EVENTS_TEMPLATE_PATH.'event_tickets_metabox_ticket_row.template.php',
1706 1706
             $ticket
1707 1707
         );
1708 1708
         return EEH_Template::display_template($template, $template_args, true);
@@ -1756,7 +1756,7 @@  discard block
 block discarded – undo
1756 1756
             $default_reg_status_values
1757 1757
         );
1758 1758
         EEH_Template::display_template(
1759
-            EVENTS_TEMPLATE_PATH . 'event_registration_options.template.php',
1759
+            EVENTS_TEMPLATE_PATH.'event_registration_options.template.php',
1760 1760
             $template_args
1761 1761
         );
1762 1762
     }
@@ -1778,7 +1778,7 @@  discard block
 block discarded – undo
1778 1778
     {
1779 1779
         $EEME = $this->_event_model();
1780 1780
         $offset = ($current_page - 1) * $per_page;
1781
-        $limit = $count ? null : $offset . ',' . $per_page;
1781
+        $limit = $count ? null : $offset.','.$per_page;
1782 1782
         $orderby = isset($this->_req_data['orderby']) ? $this->_req_data['orderby'] : 'EVT_ID';
1783 1783
         $order = isset($this->_req_data['order']) ? $this->_req_data['order'] : "DESC";
1784 1784
         if (isset($this->_req_data['month_range'])) {
@@ -1807,7 +1807,7 @@  discard block
 block discarded – undo
1807 1807
         // categories?
1808 1808
         $category = isset($this->_req_data['EVT_CAT']) && $this->_req_data['EVT_CAT'] > 0
1809 1809
             ? $this->_req_data['EVT_CAT'] : null;
1810
-        if (! empty($category)) {
1810
+        if ( ! empty($category)) {
1811 1811
             $where['Term_Taxonomy.taxonomy'] = EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY;
1812 1812
             $where['Term_Taxonomy.term_id'] = $category;
1813 1813
         }
@@ -1815,7 +1815,7 @@  discard block
 block discarded – undo
1815 1815
         $start_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start');
1816 1816
         if (isset($this->_req_data['month_range']) && $this->_req_data['month_range'] != '') {
1817 1817
             $DateTime = new DateTime(
1818
-                $year_r . '-' . $month_r . '-01 00:00:00',
1818
+                $year_r.'-'.$month_r.'-01 00:00:00',
1819 1819
                 new DateTimeZone(EEM_Datetime::instance()->get_timezone())
1820 1820
             );
1821 1821
             $start = $DateTime->format(implode(' ', $start_formats));
@@ -1841,11 +1841,11 @@  discard block
 block discarded – undo
1841 1841
                             ->format(implode(' ', $start_formats));
1842 1842
             $where['Datetime.DTT_EVT_start'] = array('BETWEEN', array($start, $end));
1843 1843
         }
1844
-        if (! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1844
+        if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_others_events', 'get_events')) {
1845 1845
             $where['EVT_wp_user'] = get_current_user_id();
1846 1846
         } else {
1847
-            if (! isset($where['status'])) {
1848
-                if (! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1847
+            if ( ! isset($where['status'])) {
1848
+                if ( ! EE_Registry::instance()->CAP->current_user_can('ee_read_private_events', 'get_events')) {
1849 1849
                     $where['OR'] = array(
1850 1850
                         'status*restrict_private' => array('!=', 'private'),
1851 1851
                         'AND'                     => array(
@@ -1865,7 +1865,7 @@  discard block
 block discarded – undo
1865 1865
         }
1866 1866
         // search query handling
1867 1867
         if (isset($this->_req_data['s'])) {
1868
-            $search_string = '%' . $this->_req_data['s'] . '%';
1868
+            $search_string = '%'.$this->_req_data['s'].'%';
1869 1869
             $where['OR'] = array(
1870 1870
                 'EVT_name'       => array('LIKE', $search_string),
1871 1871
                 'EVT_desc'       => array('LIKE', $search_string),
@@ -1960,7 +1960,7 @@  discard block
 block discarded – undo
1960 1960
             // clean status
1961 1961
             $event_status = sanitize_key($event_status);
1962 1962
             // grab status
1963
-            if (! empty($event_status)) {
1963
+            if ( ! empty($event_status)) {
1964 1964
                 $success = $this->_change_event_status($EVT_ID, $event_status);
1965 1965
             } else {
1966 1966
                 $success = false;
@@ -1997,7 +1997,7 @@  discard block
 block discarded – undo
1997 1997
         // clean status
1998 1998
         $event_status = sanitize_key($event_status);
1999 1999
         // grab status
2000
-        if (! empty($event_status)) {
2000
+        if ( ! empty($event_status)) {
2001 2001
             $success = true;
2002 2002
             // determine the event id and set to array.
2003 2003
             $EVT_IDs = isset($this->_req_data['EVT_IDs']) ? (array) $this->_req_data['EVT_IDs'] : array();
@@ -2044,7 +2044,7 @@  discard block
 block discarded – undo
2044 2044
     private function _change_event_status($EVT_ID = 0, $event_status = '')
2045 2045
     {
2046 2046
         // grab event id
2047
-        if (! $EVT_ID) {
2047
+        if ( ! $EVT_ID) {
2048 2048
             $msg = esc_html__(
2049 2049
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2050 2050
                 'event_espresso'
@@ -2159,7 +2159,7 @@  discard block
 block discarded – undo
2159 2159
         if ($_SERVER['REQUEST_METHOD'] == 'POST') {
2160 2160
             // Initialize the form from the request, and check if its valid.
2161 2161
             $this->form->receive_form_submission($this->_req_data);
2162
-            if($this->form->is_valid()){
2162
+            if ($this->form->is_valid()) {
2163 2163
                 // Redirect the user to the deletion batch job.
2164 2164
                 EEH_URL::safeRedirectAndExit(
2165 2165
                     EE_Admin_Page::add_query_args_and_nonce(
@@ -2207,14 +2207,14 @@  discard block
 block discarded – undo
2207 2207
      */
2208 2208
     protected function getModelsAndIdsToDelete($deletion_job_code)
2209 2209
     {
2210
-        if( ! $deletion_job_code){
2210
+        if ( ! $deletion_job_code) {
2211 2211
             throw new Exception(esc_html__('We aren’t sure which job you are performing. Please press back in your browser and try again.', 'event_espresso'));
2212 2212
         }
2213
-        $deletion_data = get_option('ee_deletion_' . $deletion_job_code, []);
2213
+        $deletion_data = get_option('ee_deletion_'.$deletion_job_code, []);
2214 2214
 
2215 2215
         $models_and_ids_to_delete = [];
2216 2216
         foreach ($deletion_data as $root) {
2217
-            if (! $root instanceof ModelObjNode) {
2217
+            if ( ! $root instanceof ModelObjNode) {
2218 2218
                 throw new UnexpectedEntityException($root, 'ModelObjNode');
2219 2219
             }
2220 2220
             $models_and_ids_to_delete = array_replace_recursive($models_and_ids_to_delete, $root->getIds());
@@ -2229,12 +2229,12 @@  discard block
 block discarded – undo
2229 2229
     protected function previewDeletion()
2230 2230
     {
2231 2231
         $deletion_job_code = isset($this->_req_data['deletion_job_code']) ? $this->_req_data['deletion_job_code'] : '';
2232
-        if(! $this->form instanceof ConfirmEventDeletionForm){
2232
+        if ( ! $this->form instanceof ConfirmEventDeletionForm) {
2233 2233
             $this->models_and_ids_to_delete = $this->getModelsAndIdsToDelete($deletion_job_code);
2234 2234
             $this->form = new ConfirmEventDeletionForm($this->models_and_ids_to_delete['Event']);
2235 2235
         }
2236 2236
         // If they're not in debug mode, don't list all model objectss that will be deleted. They'll just be confused.
2237
-        if(! WP_DEBUG){
2237
+        if ( ! WP_DEBUG) {
2238 2238
             $models_to_mention = [
2239 2239
                 'Event',
2240 2240
                 'Datetime',
@@ -2250,7 +2250,7 @@  discard block
 block discarded – undo
2250 2250
         ];
2251 2251
 
2252 2252
         $this->_template_args['admin_page_content'] = EEH_Template::display_template(
2253
-            EVENTS_TEMPLATE_PATH . 'event_preview_deletion.template.php',
2253
+            EVENTS_TEMPLATE_PATH.'event_preview_deletion.template.php',
2254 2254
             [
2255 2255
                 'form_url' => EE_Admin_Page::add_query_args_and_nonce(
2256 2256
                     $confirm_deletion_args,
@@ -2275,7 +2275,7 @@  discard block
 block discarded – undo
2275 2275
     private function _permanently_delete_event($EVT_ID = 0)
2276 2276
     {
2277 2277
         // grab event id
2278
-        if (! $EVT_ID) {
2278
+        if ( ! $EVT_ID) {
2279 2279
             $msg = esc_html__(
2280 2280
                 'An error occurred. No Event ID or an invalid Event ID was received.',
2281 2281
                 'event_espresso'
@@ -2283,12 +2283,12 @@  discard block
 block discarded – undo
2283 2283
             EE_Error::add_error($msg, __FILE__, __FUNCTION__, __LINE__);
2284 2284
             return false;
2285 2285
         }
2286
-        if (! $this->_cpt_model_obj instanceof EE_Event
2286
+        if ( ! $this->_cpt_model_obj instanceof EE_Event
2287 2287
             || $this->_cpt_model_obj->ID() !== $EVT_ID
2288 2288
         ) {
2289 2289
             $this->_cpt_model_obj = EEM_Event::instance()->get_one_by_ID($EVT_ID);
2290 2290
         }
2291
-        if (! $this->_cpt_model_obj instanceof EE_Event) {
2291
+        if ( ! $this->_cpt_model_obj instanceof EE_Event) {
2292 2292
             return false;
2293 2293
         }
2294 2294
         // need to delete related tickets and prices first.
@@ -2310,7 +2310,7 @@  discard block
 block discarded – undo
2310 2310
         }
2311 2311
         // any attached question groups?
2312 2312
         $question_groups = $this->_cpt_model_obj->get_many_related('Question_Group');
2313
-        if (! empty($question_groups)) {
2313
+        if ( ! empty($question_groups)) {
2314 2314
             foreach ($question_groups as $question_group) {
2315 2315
                 $this->_cpt_model_obj->_remove_relation_to($question_group, 'Question_Group');
2316 2316
             }
@@ -2521,7 +2521,7 @@  discard block
 block discarded – undo
2521 2521
                                                 . esc_html__(
2522 2522
                                                     'Template Settings is a feature that is only available in the premium version of Event Espresso 4 which is available with a support license purchase on EventEspresso.com. Template Settings allow you to configure some of the appearance options for both the Event List and Event Details pages.',
2523 2523
                                                     'event_espresso'
2524
-                                                ) . '</strong>';
2524
+                                                ).'</strong>';
2525 2525
         $this->display_admin_caf_preview_page('template_settings_tab');
2526 2526
     }
2527 2527
 
@@ -2541,12 +2541,12 @@  discard block
 block discarded – undo
2541 2541
         // set default category object
2542 2542
         $this->_set_empty_category_object();
2543 2543
         // only set if we've got an id
2544
-        if (! isset($this->_req_data['EVT_CAT_ID'])) {
2544
+        if ( ! isset($this->_req_data['EVT_CAT_ID'])) {
2545 2545
             return;
2546 2546
         }
2547 2547
         $category_id = absint($this->_req_data['EVT_CAT_ID']);
2548 2548
         $term = get_term($category_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2549
-        if (! empty($term)) {
2549
+        if ( ! empty($term)) {
2550 2550
             $this->_category->category_name = $term->name;
2551 2551
             $this->_category->category_identifier = $term->slug;
2552 2552
             $this->_category->category_desc = $term->description;
@@ -2574,7 +2574,7 @@  discard block
 block discarded – undo
2574 2574
     {
2575 2575
         do_action('AHEE_log', __FILE__, __FUNCTION__, '');
2576 2576
         $this->_search_btn_label = esc_html__('Categories', 'event_espresso');
2577
-        $this->_admin_page_title .= ' ' . $this->get_action_link_or_button(
2577
+        $this->_admin_page_title .= ' '.$this->get_action_link_or_button(
2578 2578
             'add_category',
2579 2579
             'add_category',
2580 2580
             array(),
@@ -2648,7 +2648,7 @@  discard block
 block discarded – undo
2648 2648
             'disable'                  => '',
2649 2649
             'disabled_message'         => false,
2650 2650
         );
2651
-        $template = EVENTS_TEMPLATE_PATH . 'event_category_details.template.php';
2651
+        $template = EVENTS_TEMPLATE_PATH.'event_category_details.template.php';
2652 2652
         return EEH_Template::display_template($template, $template_args, true);
2653 2653
     }
2654 2654
 
@@ -2733,7 +2733,7 @@  discard block
 block discarded – undo
2733 2733
         $insert_ids = $update
2734 2734
             ? wp_update_term($cat_id, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args)
2735 2735
             : wp_insert_term($category_name, EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY, $term_args);
2736
-        if (! is_array($insert_ids)) {
2736
+        if ( ! is_array($insert_ids)) {
2737 2737
             $msg = esc_html__(
2738 2738
                 'An error occurred and the category has not been saved to the database.',
2739 2739
                 'event_espresso'
@@ -2764,7 +2764,7 @@  discard block
 block discarded – undo
2764 2764
         $limit = ($current_page - 1) * $per_page;
2765 2765
         $where = array('taxonomy' => EEM_CPT_Base::EVENT_CATEGORY_TAXONOMY);
2766 2766
         if (isset($this->_req_data['s'])) {
2767
-            $sstr = '%' . $this->_req_data['s'] . '%';
2767
+            $sstr = '%'.$this->_req_data['s'].'%';
2768 2768
             $where['OR'] = array(
2769 2769
                 'Term.name'   => array('LIKE', $sstr),
2770 2770
                 'description' => array('LIKE', $sstr),
@@ -2773,7 +2773,7 @@  discard block
 block discarded – undo
2773 2773
         $query_params = array(
2774 2774
             $where,
2775 2775
             'order_by'   => array($orderby => $order),
2776
-            'limit'      => $limit . ',' . $per_page,
2776
+            'limit'      => $limit.','.$per_page,
2777 2777
             'force_join' => array('Term'),
2778 2778
         );
2779 2779
         $categories = $count
Please login to merge, or discard this patch.
admin_pages/events/templates/event_preview_deletion.template.php 2 patches
Indentation   +43 added lines, -43 removed lines patch added patch discarded remove patch
@@ -5,58 +5,58 @@
 block discarded – undo
5 5
     <?php
6 6
 }
7 7
 foreach ($models_and_ids_to_delete as $model_name => $ids) {
8
-    $model = EE_Registry::instance()->load_model($model_name);
9
-    $count = count($ids);
10
-    ?><h3><?php echo esc_html(
11
-        sprintf(
12
-            _x('%1$d %2$s', 'Count of items', 'event_espresso'),
13
-            $count,
14
-            $model->item_name($count)
15
-        )
16
-    ); ?></h3>
8
+	$model = EE_Registry::instance()->load_model($model_name);
9
+	$count = count($ids);
10
+	?><h3><?php echo esc_html(
11
+		sprintf(
12
+			_x('%1$d %2$s', 'Count of items', 'event_espresso'),
13
+			$count,
14
+			$model->item_name($count)
15
+		)
16
+	); ?></h3>
17 17
     <?php
18
-    $sample_only = false;
19
-    if ($count > $quantity_to_preview) {
20
-        $sample_only = true;
21
-        $ids = array_slice($ids, 0, $quantity_to_preview);
22
-    }
23
-    if ($sample_only) {
24
-        ?><p><?php
25
-        echo esc_html(
26
-            sprintf(
27
-                __('First %1$d %2$s to Delete...', 'event_espresso'),
28
-                count($ids),
29
-                $model->item_name($count)
30
-            )
31
-        ); ?></p>
18
+	$sample_only = false;
19
+	if ($count > $quantity_to_preview) {
20
+		$sample_only = true;
21
+		$ids = array_slice($ids, 0, $quantity_to_preview);
22
+	}
23
+	if ($sample_only) {
24
+		?><p><?php
25
+		echo esc_html(
26
+			sprintf(
27
+				__('First %1$d %2$s to Delete...', 'event_espresso'),
28
+				count($ids),
29
+				$model->item_name($count)
30
+			)
31
+		); ?></p>
32 32
         <?php
33
-    }
34
-    ?>
33
+	}
34
+	?>
35 35
     <ul>
36 36
         <?php foreach ($ids as $id) {
37
-            $model_obj = $model->get_one_by_ID($id);
38
-            if (!$model_obj instanceof EE_Base_Class) {
39
-                continue;
40
-            }
41
-            if ($model_obj instanceof EE_Datetime) {
42
-                $model_obj_name = $model_obj->get_dtt_display_name(true);
43
-            } else {
44
-                $model_obj_name = $model_obj->name();
45
-            }
37
+			$model_obj = $model->get_one_by_ID($id);
38
+			if (!$model_obj instanceof EE_Base_Class) {
39
+				continue;
40
+			}
41
+			if ($model_obj instanceof EE_Datetime) {
42
+				$model_obj_name = $model_obj->get_dtt_display_name(true);
43
+			} else {
44
+				$model_obj_name = $model_obj->name();
45
+			}
46 46
 
47
-            ?>
47
+			?>
48 48
             <li>
49 49
                 <?php echo esc_html(
50
-                    sprintf(
51
-                        _x('%1$s (ID "%2$s")', 'Model object name (ID)', 'event_espresso'),
52
-                        $model_obj_name,
53
-                        $model_obj->ID()
54
-                    )
55
-                ); ?>
50
+					sprintf(
51
+						_x('%1$s (ID "%2$s")', 'Model object name (ID)', 'event_espresso'),
52
+						$model_obj_name,
53
+						$model_obj->ID()
54
+					)
55
+				); ?>
56 56
             </li>
57 57
             <?php
58
-        }
59
-        ?>
58
+		}
59
+		?>
60 60
     </ul>
61 61
 
62 62
 
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -35,7 +35,7 @@  discard block
 block discarded – undo
35 35
     <ul>
36 36
         <?php foreach ($ids as $id) {
37 37
             $model_obj = $model->get_one_by_ID($id);
38
-            if (!$model_obj instanceof EE_Base_Class) {
38
+            if ( ! $model_obj instanceof EE_Base_Class) {
39 39
                 continue;
40 40
             }
41 41
             if ($model_obj instanceof EE_Datetime) {
@@ -64,6 +64,6 @@  discard block
 block discarded – undo
64 64
 }
65 65
 ?>
66 66
 <form action="<?php echo $form_url; ?>" method="POST">
67
-    <?php echo $form->get_html_and_js();?>
67
+    <?php echo $form->get_html_and_js(); ?>
68 68
     <input type="submit" value="<?php echo esc_attr(esc_html__('Confirm', 'event_espresso')); ?>">
69 69
 </form>
Please login to merge, or discard this patch.
admin_pages/events/form_sections/ConfirmEventDeletionForm.php 2 patches
Indentation   +64 added lines, -64 removed lines patch added patch discarded remove patch
@@ -19,71 +19,71 @@
 block discarded – undo
19 19
  */
20 20
 class ConfirmEventDeletionForm extends \EE_Form_Section_Proper
21 21
 {
22
-    /**
23
-     * @var EE_Event[]
24
-     */
25
-    protected $events;
26
-    public function __construct($event_ids, $options_array = array())
27
-    {
28
-        if(! isset($options_array['subsections'])){
29
-            $options_array['subsections'] = [];
30
-        }
31
-        if(! isset($options_array['subsections']['events'])){
32
-            $events_subsection = new \EE_Form_Section_Proper();
33
-            $options_array['subsections']['events'] = $events_subsection;
34
-        }
35
-        $events = EEM_Event::instance()->get_all_deleted(
36
-            [
37
-                [
38
-                    'EVT_ID' => ['IN',$event_ids]
39
-                ]
40
-            ]
41
-        );
42
-        if( ! is_array($events)){
43
-            throw new UnexpectedEntityException($event_ids, 'array');
44
-        }
45
-        $this->events = $events;
46
-        $events_inputs = [];
47
-        foreach($events as $event){
48
-             $events_inputs[$event->slug()] = new \EE_Text_Input(
49
-                [
50
-                    'html_label_text' => esc_html(
51
-                        sprintf(
52
-                            __('You are about to delete the event "%1$s" (whose URL slug is "%2$s"). Please confirm the URL slug of the event', 'event_espresso'),
53
-                            $event->name(),
54
-                            $event->slug()
55
-                        )
56
-                    ),
57
-                    'required' => true
58
-                ]
59
-            );
60
-        }
61
-        $events_subsection->add_subsections($events_inputs);
62
-        $options_array['subsections']['backup'] = new EE_Checkbox_Multi_Input(
63
-            [
64
-                'yes' => esc_html__('I have backed up my database.', 'event_espresso')
65
-            ],
66
-            [
67
-                'html_label_text' => esc_html__('Deleting this data cannot be undone. Please confirm you have a usable database backup.', 'event_espresso'),
68
-                'required' => true
69
-            ]
70
-        );
71
-        parent::__construct($options_array);
72
-    }
22
+	/**
23
+	 * @var EE_Event[]
24
+	 */
25
+	protected $events;
26
+	public function __construct($event_ids, $options_array = array())
27
+	{
28
+		if(! isset($options_array['subsections'])){
29
+			$options_array['subsections'] = [];
30
+		}
31
+		if(! isset($options_array['subsections']['events'])){
32
+			$events_subsection = new \EE_Form_Section_Proper();
33
+			$options_array['subsections']['events'] = $events_subsection;
34
+		}
35
+		$events = EEM_Event::instance()->get_all_deleted(
36
+			[
37
+				[
38
+					'EVT_ID' => ['IN',$event_ids]
39
+				]
40
+			]
41
+		);
42
+		if( ! is_array($events)){
43
+			throw new UnexpectedEntityException($event_ids, 'array');
44
+		}
45
+		$this->events = $events;
46
+		$events_inputs = [];
47
+		foreach($events as $event){
48
+			 $events_inputs[$event->slug()] = new \EE_Text_Input(
49
+				[
50
+					'html_label_text' => esc_html(
51
+						sprintf(
52
+							__('You are about to delete the event "%1$s" (whose URL slug is "%2$s"). Please confirm the URL slug of the event', 'event_espresso'),
53
+							$event->name(),
54
+							$event->slug()
55
+						)
56
+					),
57
+					'required' => true
58
+				]
59
+			);
60
+		}
61
+		$events_subsection->add_subsections($events_inputs);
62
+		$options_array['subsections']['backup'] = new EE_Checkbox_Multi_Input(
63
+			[
64
+				'yes' => esc_html__('I have backed up my database.', 'event_espresso')
65
+			],
66
+			[
67
+				'html_label_text' => esc_html__('Deleting this data cannot be undone. Please confirm you have a usable database backup.', 'event_espresso'),
68
+				'required' => true
69
+			]
70
+		);
71
+		parent::__construct($options_array);
72
+	}
73 73
 
74
-    public function _validate()
75
-    {
76
-        parent::_validate(); // TODO: Change the autogenerated stub
77
-        $events_subsection = $this->get_proper_subsection('events');
78
-        foreach($this->events as $event){
79
-            $event_input = $events_subsection->get_input($event->slug());
80
-            if($event_input->normalized_value() !== $event->slug()){
81
-                $event_input->add_validation_error(
82
-                    esc_html__('We ask you confirm the event’s slug in order to avoid accidentally deleting the wrong event. Please enter the correct slug for this event.', 'event_espresso')
83
-                );
84
-            }
85
-        }
86
-    }
74
+	public function _validate()
75
+	{
76
+		parent::_validate(); // TODO: Change the autogenerated stub
77
+		$events_subsection = $this->get_proper_subsection('events');
78
+		foreach($this->events as $event){
79
+			$event_input = $events_subsection->get_input($event->slug());
80
+			if($event_input->normalized_value() !== $event->slug()){
81
+				$event_input->add_validation_error(
82
+					esc_html__('We ask you confirm the event’s slug in order to avoid accidentally deleting the wrong event. Please enter the correct slug for this event.', 'event_espresso')
83
+				);
84
+			}
85
+		}
86
+	}
87 87
 
88 88
 }
89 89
 // End of file ConfirmEventDeletionForm.php
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -25,26 +25,26 @@  discard block
 block discarded – undo
25 25
     protected $events;
26 26
     public function __construct($event_ids, $options_array = array())
27 27
     {
28
-        if(! isset($options_array['subsections'])){
28
+        if ( ! isset($options_array['subsections'])) {
29 29
             $options_array['subsections'] = [];
30 30
         }
31
-        if(! isset($options_array['subsections']['events'])){
31
+        if ( ! isset($options_array['subsections']['events'])) {
32 32
             $events_subsection = new \EE_Form_Section_Proper();
33 33
             $options_array['subsections']['events'] = $events_subsection;
34 34
         }
35 35
         $events = EEM_Event::instance()->get_all_deleted(
36 36
             [
37 37
                 [
38
-                    'EVT_ID' => ['IN',$event_ids]
38
+                    'EVT_ID' => ['IN', $event_ids]
39 39
                 ]
40 40
             ]
41 41
         );
42
-        if( ! is_array($events)){
42
+        if ( ! is_array($events)) {
43 43
             throw new UnexpectedEntityException($event_ids, 'array');
44 44
         }
45 45
         $this->events = $events;
46 46
         $events_inputs = [];
47
-        foreach($events as $event){
47
+        foreach ($events as $event) {
48 48
              $events_inputs[$event->slug()] = new \EE_Text_Input(
49 49
                 [
50 50
                     'html_label_text' => esc_html(
@@ -75,9 +75,9 @@  discard block
 block discarded – undo
75 75
     {
76 76
         parent::_validate(); // TODO: Change the autogenerated stub
77 77
         $events_subsection = $this->get_proper_subsection('events');
78
-        foreach($this->events as $event){
78
+        foreach ($this->events as $event) {
79 79
             $event_input = $events_subsection->get_input($event->slug());
80
-            if($event_input->normalized_value() !== $event->slug()){
80
+            if ($event_input->normalized_value() !== $event->slug()) {
81 81
                 $event_input->add_validation_error(
82 82
                     esc_html__('We ask you confirm the event’s slug in order to avoid accidentally deleting the wrong event. Please enter the correct slug for this event.', 'event_espresso')
83 83
                 );
Please login to merge, or discard this patch.
core/db_classes/EE_Registration.class.php 2 patches
Indentation   +2085 added lines, -2085 removed lines patch added patch discarded remove patch
@@ -17,2089 +17,2089 @@
 block discarded – undo
17 17
 {
18 18
 
19 19
 
20
-    /**
21
-     * Used to reference when a registration has never been checked in.
22
-     *
23
-     * @deprecated use \EE_Checkin::status_checked_never instead
24
-     * @type int
25
-     */
26
-    const checkin_status_never = 2;
27
-
28
-    /**
29
-     * Used to reference when a registration has been checked in.
30
-     *
31
-     * @deprecated use \EE_Checkin::status_checked_in instead
32
-     * @type int
33
-     */
34
-    const checkin_status_in = 1;
35
-
36
-
37
-    /**
38
-     * Used to reference when a registration has been checked out.
39
-     *
40
-     * @deprecated use \EE_Checkin::status_checked_out instead
41
-     * @type int
42
-     */
43
-    const checkin_status_out = 0;
44
-
45
-
46
-    /**
47
-     * extra meta key for tracking reg status os trashed registrations
48
-     *
49
-     * @type string
50
-     */
51
-    const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
52
-
53
-
54
-    /**
55
-     * extra meta key for tracking if registration has reserved ticket
56
-     *
57
-     * @type string
58
-     */
59
-    const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
60
-
61
-
62
-    /**
63
-     * @param array  $props_n_values          incoming values
64
-     * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
65
-     *                                        used.)
66
-     * @param array  $date_formats            incoming date_formats in an array where the first value is the
67
-     *                                        date_format and the second value is the time format
68
-     * @return EE_Registration
69
-     * @throws EE_Error
70
-     */
71
-    public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
72
-    {
73
-        $has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
74
-        return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
75
-    }
76
-
77
-
78
-    /**
79
-     * @param array  $props_n_values  incoming values from the database
80
-     * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
-     *                                the website will be used.
82
-     * @return EE_Registration
83
-     */
84
-    public static function new_instance_from_db($props_n_values = array(), $timezone = null)
85
-    {
86
-        return new self($props_n_values, true, $timezone);
87
-    }
88
-
89
-
90
-    /**
91
-     *        Set Event ID
92
-     *
93
-     * @param        int $EVT_ID Event ID
94
-     * @throws EE_Error
95
-     * @throws RuntimeException
96
-     */
97
-    public function set_event($EVT_ID = 0)
98
-    {
99
-        $this->set('EVT_ID', $EVT_ID);
100
-    }
101
-
102
-
103
-    /**
104
-     * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
105
-     * be routed to internal methods
106
-     *
107
-     * @param string $field_name
108
-     * @param mixed  $field_value
109
-     * @param bool   $use_default
110
-     * @throws EE_Error
111
-     * @throws EntityNotFoundException
112
-     * @throws InvalidArgumentException
113
-     * @throws InvalidDataTypeException
114
-     * @throws InvalidInterfaceException
115
-     * @throws ReflectionException
116
-     * @throws RuntimeException
117
-     */
118
-    public function set($field_name, $field_value, $use_default = false)
119
-    {
120
-        switch ($field_name) {
121
-            case 'REG_code':
122
-                if (! empty($field_value) && $this->reg_code() === null) {
123
-                    $this->set_reg_code($field_value, $use_default);
124
-                }
125
-                break;
126
-            case 'STS_ID':
127
-                $this->set_status($field_value, $use_default);
128
-                break;
129
-            default:
130
-                parent::set($field_name, $field_value, $use_default);
131
-        }
132
-    }
133
-
134
-
135
-    /**
136
-     * Set Status ID
137
-     * updates the registration status and ALSO...
138
-     * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
139
-     * calls release_registration_space() if the reg status changes FROM approved to any other reg status
140
-     *
141
-     * @param string                $new_STS_ID
142
-     * @param boolean               $use_default
143
-     * @param ContextInterface|null $context
144
-     * @return bool
145
-     * @throws DomainException
146
-     * @throws EE_Error
147
-     * @throws EntityNotFoundException
148
-     * @throws InvalidArgumentException
149
-     * @throws InvalidDataTypeException
150
-     * @throws InvalidInterfaceException
151
-     * @throws ReflectionException
152
-     * @throws RuntimeException
153
-     * @throws UnexpectedEntityException
154
-     */
155
-    public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
156
-    {
157
-        // get current REG_Status
158
-        $old_STS_ID = $this->status_ID();
159
-        // if status has changed
160
-        if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
161
-            && ! empty($old_STS_ID) // and that old status is actually set
162
-            && ! empty($new_STS_ID) // as well as the new status
163
-            && $this->ID() // ensure registration is in the db
164
-        ) {
165
-            // update internal status first
166
-            parent::set('STS_ID', $new_STS_ID, $use_default);
167
-            // THEN handle other changes that occur when reg status changes
168
-            // TO approved
169
-            if ($new_STS_ID === EEM_Registration::status_id_approved) {
170
-                // reserve a space by incrementing ticket and datetime sold values
171
-                $this->reserveRegistrationSpace();
172
-                do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
173
-                // OR FROM  approved
174
-            } elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
175
-                // release a space by decrementing ticket and datetime sold values
176
-                $this->releaseRegistrationSpace();
177
-                do_action(
178
-                    'AHEE__EE_Registration__set_status__from_approved',
179
-                    $this,
180
-                    $old_STS_ID,
181
-                    $new_STS_ID,
182
-                    $context
183
-                );
184
-            }
185
-            // update status
186
-            parent::set('STS_ID', $new_STS_ID, $use_default);
187
-            $this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
188
-            if ($this->statusChangeUpdatesTransaction($context)) {
189
-                $this->updateTransactionAfterStatusChange();
190
-            }
191
-            do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
192
-            return true;
193
-        }
194
-        // even though the old value matches the new value, it's still good to
195
-        // allow the parent set method to have a say
196
-        parent::set('STS_ID', $new_STS_ID, $use_default);
197
-        return true;
198
-    }
199
-
200
-
201
-    /**
202
-     * update REGs and TXN when cancelled or declined registrations involved
203
-     *
204
-     * @param string                $new_STS_ID
205
-     * @param string                $old_STS_ID
206
-     * @param ContextInterface|null $context
207
-     * @throws EE_Error
208
-     * @throws InvalidArgumentException
209
-     * @throws InvalidDataTypeException
210
-     * @throws InvalidInterfaceException
211
-     * @throws ReflectionException
212
-     * @throws RuntimeException
213
-     */
214
-    private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
215
-    {
216
-        // these reg statuses should not be considered in any calculations involving monies owing
217
-        $closed_reg_statuses = EEM_Registration::closed_reg_statuses();
218
-        // true if registration has been cancelled or declined
219
-        $this->updateIfCanceled(
220
-            $closed_reg_statuses,
221
-            $new_STS_ID,
222
-            $old_STS_ID,
223
-            $context
224
-        );
225
-        $this->updateIfReinstated(
226
-            $closed_reg_statuses,
227
-            $new_STS_ID,
228
-            $old_STS_ID,
229
-            $context
230
-        );
231
-    }
232
-
233
-
234
-    /**
235
-     * update REGs and TXN when cancelled or declined registrations involved
236
-     *
237
-     * @param array                 $closed_reg_statuses
238
-     * @param string                $new_STS_ID
239
-     * @param string                $old_STS_ID
240
-     * @param ContextInterface|null $context
241
-     * @throws EE_Error
242
-     * @throws InvalidArgumentException
243
-     * @throws InvalidDataTypeException
244
-     * @throws InvalidInterfaceException
245
-     * @throws ReflectionException
246
-     * @throws RuntimeException
247
-     */
248
-    private function updateIfCanceled(
249
-        array $closed_reg_statuses,
250
-        $new_STS_ID,
251
-        $old_STS_ID,
252
-        ContextInterface $context = null
253
-    ) {
254
-        // true if registration has been cancelled or declined
255
-        if (in_array($new_STS_ID, $closed_reg_statuses, true)
256
-            && ! in_array($old_STS_ID, $closed_reg_statuses, true)
257
-        ) {
258
-            /** @type EE_Registration_Processor $registration_processor */
259
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
260
-            /** @type EE_Transaction_Processor $transaction_processor */
261
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
262
-            // cancelled or declined registration
263
-            $registration_processor->update_registration_after_being_canceled_or_declined(
264
-                $this,
265
-                $closed_reg_statuses
266
-            );
267
-            $transaction_processor->update_transaction_after_canceled_or_declined_registration(
268
-                $this,
269
-                $closed_reg_statuses,
270
-                false
271
-            );
272
-            do_action(
273
-                'AHEE__EE_Registration__set_status__canceled_or_declined',
274
-                $this,
275
-                $old_STS_ID,
276
-                $new_STS_ID,
277
-                $context
278
-            );
279
-            return;
280
-        }
281
-    }
282
-
283
-
284
-    /**
285
-     * update REGs and TXN when cancelled or declined registrations involved
286
-     *
287
-     * @param array                 $closed_reg_statuses
288
-     * @param string                $new_STS_ID
289
-     * @param string                $old_STS_ID
290
-     * @param ContextInterface|null $context
291
-     * @throws EE_Error
292
-     * @throws InvalidArgumentException
293
-     * @throws InvalidDataTypeException
294
-     * @throws InvalidInterfaceException
295
-     * @throws ReflectionException
296
-     */
297
-    private function updateIfReinstated(
298
-        array $closed_reg_statuses,
299
-        $new_STS_ID,
300
-        $old_STS_ID,
301
-        ContextInterface $context = null
302
-    ) {
303
-        // true if reinstating cancelled or declined registration
304
-        if (in_array($old_STS_ID, $closed_reg_statuses, true)
305
-            && ! in_array($new_STS_ID, $closed_reg_statuses, true)
306
-        ) {
307
-            /** @type EE_Registration_Processor $registration_processor */
308
-            $registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
309
-            /** @type EE_Transaction_Processor $transaction_processor */
310
-            $transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
311
-            // reinstating cancelled or declined registration
312
-            $registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
313
-                $this,
314
-                $closed_reg_statuses
315
-            );
316
-            $transaction_processor->update_transaction_after_reinstating_canceled_registration(
317
-                $this,
318
-                $closed_reg_statuses,
319
-                false
320
-            );
321
-            do_action(
322
-                'AHEE__EE_Registration__set_status__after_reinstated',
323
-                $this,
324
-                $old_STS_ID,
325
-                $new_STS_ID,
326
-                $context
327
-            );
328
-        }
329
-    }
330
-
331
-
332
-    /**
333
-     * @param ContextInterface|null $context
334
-     * @return bool
335
-     */
336
-    private function statusChangeUpdatesTransaction(ContextInterface $context = null)
337
-    {
338
-        $contexts_that_do_not_update_transaction = (array) apply_filters(
339
-            'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
340
-            array('spco_reg_step_attendee_information_process_registrations'),
341
-            $context,
342
-            $this
343
-        );
344
-        return ! (
345
-            $context instanceof ContextInterface
346
-            && in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
347
-        );
348
-    }
349
-
350
-
351
-    /**
352
-     * @throws EE_Error
353
-     * @throws EntityNotFoundException
354
-     * @throws InvalidArgumentException
355
-     * @throws InvalidDataTypeException
356
-     * @throws InvalidInterfaceException
357
-     * @throws ReflectionException
358
-     * @throws RuntimeException
359
-     */
360
-    private function updateTransactionAfterStatusChange()
361
-    {
362
-        /** @type EE_Transaction_Payments $transaction_payments */
363
-        $transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
364
-        $transaction_payments->recalculate_transaction_total($this->transaction(), false);
365
-        $this->transaction()->update_status_based_on_total_paid(true);
366
-    }
367
-
368
-
369
-    /**
370
-     *        get Status ID
371
-     */
372
-    public function status_ID()
373
-    {
374
-        return $this->get('STS_ID');
375
-    }
376
-
377
-
378
-    /**
379
-     * Gets the ticket this registration is for
380
-     *
381
-     * @param boolean $include_archived whether to include archived tickets or not.
382
-     *
383
-     * @return EE_Ticket|EE_Base_Class
384
-     * @throws EE_Error
385
-     */
386
-    public function ticket($include_archived = true)
387
-    {
388
-        $query_params = array();
389
-        if ($include_archived) {
390
-            $query_params['default_where_conditions'] = 'none';
391
-        }
392
-        return $this->get_first_related('Ticket', $query_params);
393
-    }
394
-
395
-
396
-    /**
397
-     * Gets the event this registration is for
398
-     *
399
-     * @return EE_Event
400
-     * @throws EE_Error
401
-     * @throws EntityNotFoundException
402
-     */
403
-    public function event()
404
-    {
405
-        $event = $this->get_first_related('Event');
406
-        if (! $event instanceof \EE_Event) {
407
-            throw new EntityNotFoundException('Event ID', $this->event_ID());
408
-        }
409
-        return $event;
410
-    }
411
-
412
-
413
-    /**
414
-     * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
415
-     * with the author of the event this registration is for.
416
-     *
417
-     * @since 4.5.0
418
-     * @return int
419
-     * @throws EE_Error
420
-     * @throws EntityNotFoundException
421
-     */
422
-    public function wp_user()
423
-    {
424
-        $event = $this->event();
425
-        if ($event instanceof EE_Event) {
426
-            return $event->wp_user();
427
-        }
428
-        return 0;
429
-    }
430
-
431
-
432
-    /**
433
-     * increments this registration's related ticket sold and corresponding datetime sold values
434
-     *
435
-     * @return void
436
-     * @throws DomainException
437
-     * @throws EE_Error
438
-     * @throws EntityNotFoundException
439
-     * @throws InvalidArgumentException
440
-     * @throws InvalidDataTypeException
441
-     * @throws InvalidInterfaceException
442
-     * @throws ReflectionException
443
-     * @throws UnexpectedEntityException
444
-     */
445
-    private function reserveRegistrationSpace()
446
-    {
447
-        // reserved ticket and datetime counts will be decremented as sold counts are incremented
448
-        // so stop tracking that this reg has a ticket reserved
449
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
450
-        $ticket = $this->ticket();
451
-        $ticket->increaseSold();
452
-        // possibly set event status to sold out
453
-        $this->event()->perform_sold_out_status_check();
454
-    }
455
-
456
-
457
-    /**
458
-     * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
459
-     *
460
-     * @return void
461
-     * @throws DomainException
462
-     * @throws EE_Error
463
-     * @throws EntityNotFoundException
464
-     * @throws InvalidArgumentException
465
-     * @throws InvalidDataTypeException
466
-     * @throws InvalidInterfaceException
467
-     * @throws ReflectionException
468
-     * @throws UnexpectedEntityException
469
-     */
470
-    private function releaseRegistrationSpace()
471
-    {
472
-        $ticket = $this->ticket();
473
-        $ticket->decreaseSold();
474
-        // possibly change event status from sold out back to previous status
475
-        $this->event()->perform_sold_out_status_check();
476
-    }
477
-
478
-
479
-    /**
480
-     * tracks this registration's ticket reservation in extra meta
481
-     * and can increment related ticket reserved and corresponding datetime reserved values
482
-     *
483
-     * @param bool $update_ticket if true, will increment ticket and datetime reserved count
484
-     * @return void
485
-     * @throws EE_Error
486
-     * @throws InvalidArgumentException
487
-     * @throws InvalidDataTypeException
488
-     * @throws InvalidInterfaceException
489
-     * @throws ReflectionException
490
-     */
491
-    public function reserve_ticket($update_ticket = false, $source = 'unknown')
492
-    {
493
-        // only reserve ticket if space is not currently reserved
494
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
495
-            $this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
496
-            // IMPORTANT !!!
497
-            // although checking $update_ticket first would be more efficient,
498
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
499
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
500
-                && $update_ticket
501
-            ) {
502
-                $ticket = $this->ticket();
503
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
504
-                $ticket->save();
505
-            }
506
-        }
507
-    }
508
-
509
-
510
-    /**
511
-     * stops tracking this registration's ticket reservation in extra meta
512
-     * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
513
-     *
514
-     * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
515
-     * @return void
516
-     * @throws EE_Error
517
-     * @throws InvalidArgumentException
518
-     * @throws InvalidDataTypeException
519
-     * @throws InvalidInterfaceException
520
-     * @throws ReflectionException
521
-     */
522
-    public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
523
-    {
524
-        // only release ticket if space is currently reserved
525
-        if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
526
-            $this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
527
-            // IMPORTANT !!!
528
-            // although checking $update_ticket first would be more efficient,
529
-            // we NEED to ALWAYS call update_extra_meta(), which is why that is done first
530
-            if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
531
-                && $update_ticket
532
-            ) {
533
-                $ticket = $this->ticket();
534
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
535
-            }
536
-        }
537
-    }
538
-
539
-
540
-    /**
541
-     * Set Attendee ID
542
-     *
543
-     * @param        int $ATT_ID Attendee ID
544
-     * @throws EE_Error
545
-     * @throws RuntimeException
546
-     */
547
-    public function set_attendee_id($ATT_ID = 0)
548
-    {
549
-        $this->set('ATT_ID', $ATT_ID);
550
-    }
551
-
552
-
553
-    /**
554
-     *        Set Transaction ID
555
-     *
556
-     * @param        int $TXN_ID Transaction ID
557
-     * @throws EE_Error
558
-     * @throws RuntimeException
559
-     */
560
-    public function set_transaction_id($TXN_ID = 0)
561
-    {
562
-        $this->set('TXN_ID', $TXN_ID);
563
-    }
564
-
565
-
566
-    /**
567
-     *        Set Session
568
-     *
569
-     * @param    string $REG_session PHP Session ID
570
-     * @throws EE_Error
571
-     * @throws RuntimeException
572
-     */
573
-    public function set_session($REG_session = '')
574
-    {
575
-        $this->set('REG_session', $REG_session);
576
-    }
577
-
578
-
579
-    /**
580
-     *        Set Registration URL Link
581
-     *
582
-     * @param    string $REG_url_link Registration URL Link
583
-     * @throws EE_Error
584
-     * @throws RuntimeException
585
-     */
586
-    public function set_reg_url_link($REG_url_link = '')
587
-    {
588
-        $this->set('REG_url_link', $REG_url_link);
589
-    }
590
-
591
-
592
-    /**
593
-     *        Set Attendee Counter
594
-     *
595
-     * @param        int $REG_count Primary Attendee
596
-     * @throws EE_Error
597
-     * @throws RuntimeException
598
-     */
599
-    public function set_count($REG_count = 1)
600
-    {
601
-        $this->set('REG_count', $REG_count);
602
-    }
603
-
604
-
605
-    /**
606
-     *        Set Group Size
607
-     *
608
-     * @param        boolean $REG_group_size Group Registration
609
-     * @throws EE_Error
610
-     * @throws RuntimeException
611
-     */
612
-    public function set_group_size($REG_group_size = false)
613
-    {
614
-        $this->set('REG_group_size', $REG_group_size);
615
-    }
616
-
617
-
618
-    /**
619
-     *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
620
-     *    EEM_Registration::status_id_not_approved
621
-     *
622
-     * @return        boolean
623
-     */
624
-    public function is_not_approved()
625
-    {
626
-        return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
627
-    }
628
-
629
-
630
-    /**
631
-     *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
632
-     *    EEM_Registration::status_id_pending_payment
633
-     *
634
-     * @return        boolean
635
-     */
636
-    public function is_pending_payment()
637
-    {
638
-        return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
639
-    }
640
-
641
-
642
-    /**
643
-     *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
644
-     *
645
-     * @return        boolean
646
-     */
647
-    public function is_approved()
648
-    {
649
-        return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
650
-    }
651
-
652
-
653
-    /**
654
-     *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
655
-     *
656
-     * @return        boolean
657
-     */
658
-    public function is_cancelled()
659
-    {
660
-        return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
661
-    }
662
-
663
-
664
-    /**
665
-     *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
666
-     *
667
-     * @return        boolean
668
-     */
669
-    public function is_declined()
670
-    {
671
-        return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
672
-    }
673
-
674
-
675
-    /**
676
-     *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
677
-     *    EEM_Registration::status_id_incomplete
678
-     *
679
-     * @return        boolean
680
-     */
681
-    public function is_incomplete()
682
-    {
683
-        return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
684
-    }
685
-
686
-
687
-    /**
688
-     *        Set Registration Date
689
-     *
690
-     * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
691
-     *                                                 Date
692
-     * @throws EE_Error
693
-     * @throws RuntimeException
694
-     */
695
-    public function set_reg_date($REG_date = false)
696
-    {
697
-        $this->set('REG_date', $REG_date);
698
-    }
699
-
700
-
701
-    /**
702
-     *    Set final price owing for this registration after all ticket/price modifications
703
-     *
704
-     * @access    public
705
-     * @param    float $REG_final_price
706
-     * @throws EE_Error
707
-     * @throws RuntimeException
708
-     */
709
-    public function set_final_price($REG_final_price = 0.00)
710
-    {
711
-        $this->set('REG_final_price', $REG_final_price);
712
-    }
713
-
714
-
715
-    /**
716
-     *    Set amount paid towards this registration's final price
717
-     *
718
-     * @access    public
719
-     * @param    float $REG_paid
720
-     * @throws EE_Error
721
-     * @throws RuntimeException
722
-     */
723
-    public function set_paid($REG_paid = 0.00)
724
-    {
725
-        $this->set('REG_paid', $REG_paid);
726
-    }
727
-
728
-
729
-    /**
730
-     *        Attendee Is Going
731
-     *
732
-     * @param        boolean $REG_att_is_going Attendee Is Going
733
-     * @throws EE_Error
734
-     * @throws RuntimeException
735
-     */
736
-    public function set_att_is_going($REG_att_is_going = false)
737
-    {
738
-        $this->set('REG_att_is_going', $REG_att_is_going);
739
-    }
740
-
741
-
742
-    /**
743
-     * Gets the related attendee
744
-     *
745
-     * @return EE_Attendee
746
-     * @throws EE_Error
747
-     */
748
-    public function attendee()
749
-    {
750
-        return $this->get_first_related('Attendee');
751
-    }
752
-
753
-
754
-    /**
755
-     *        get Event ID
756
-     */
757
-    public function event_ID()
758
-    {
759
-        return $this->get('EVT_ID');
760
-    }
761
-
762
-
763
-    /**
764
-     *        get Event ID
765
-     */
766
-    public function event_name()
767
-    {
768
-        $event = $this->event_obj();
769
-        if ($event) {
770
-            return $event->name();
771
-        } else {
772
-            return null;
773
-        }
774
-    }
775
-
776
-
777
-    /**
778
-     * Fetches the event this registration is for
779
-     *
780
-     * @return EE_Event
781
-     * @throws EE_Error
782
-     */
783
-    public function event_obj()
784
-    {
785
-        return $this->get_first_related('Event');
786
-    }
787
-
788
-
789
-    /**
790
-     *        get Attendee ID
791
-     */
792
-    public function attendee_ID()
793
-    {
794
-        return $this->get('ATT_ID');
795
-    }
796
-
797
-
798
-    /**
799
-     *        get PHP Session ID
800
-     */
801
-    public function session_ID()
802
-    {
803
-        return $this->get('REG_session');
804
-    }
805
-
806
-
807
-    /**
808
-     * Gets the string which represents the URL trigger for the receipt template in the message template system.
809
-     *
810
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
811
-     * @return string
812
-     */
813
-    public function receipt_url($messenger = 'html')
814
-    {
815
-
816
-        /**
817
-         * The below will be deprecated one version after this.  We check first if there is a custom receipt template
818
-         * already in use on old system.  If there is then we just return the standard url for it.
819
-         *
820
-         * @since 4.5.0
821
-         */
822
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
823
-        $has_custom = EEH_Template::locate_template(
824
-            $template_relative_path,
825
-            array(),
826
-            true,
827
-            true,
828
-            true
829
-        );
830
-
831
-        if ($has_custom) {
832
-            return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
833
-        }
834
-        return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
835
-    }
836
-
837
-
838
-    /**
839
-     * Gets the string which represents the URL trigger for the invoice template in the message template system.
840
-     *
841
-     * @param string $messenger 'pdf' or 'html'.  Default 'html'.
842
-     * @return string
843
-     * @throws EE_Error
844
-     */
845
-    public function invoice_url($messenger = 'html')
846
-    {
847
-        /**
848
-         * The below will be deprecated one version after this.  We check first if there is a custom invoice template
849
-         * already in use on old system.  If there is then we just return the standard url for it.
850
-         *
851
-         * @since 4.5.0
852
-         */
853
-        $template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
854
-        $has_custom = EEH_Template::locate_template(
855
-            $template_relative_path,
856
-            array(),
857
-            true,
858
-            true,
859
-            true
860
-        );
861
-
862
-        if ($has_custom) {
863
-            if ($messenger == 'html') {
864
-                return $this->invoice_url('launch');
865
-            }
866
-            $route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
867
-
868
-            $query_args = array('ee' => $route, 'id' => $this->reg_url_link());
869
-            if ($messenger == 'html') {
870
-                $query_args['html'] = true;
871
-            }
872
-            return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
873
-        }
874
-        return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
875
-    }
876
-
877
-
878
-    /**
879
-     * get Registration URL Link
880
-     *
881
-     * @access public
882
-     * @return string
883
-     * @throws EE_Error
884
-     */
885
-    public function reg_url_link()
886
-    {
887
-        return (string) $this->get('REG_url_link');
888
-    }
889
-
890
-
891
-    /**
892
-     * Echoes out invoice_url()
893
-     *
894
-     * @param string $type 'download','launch', or 'html' (default is 'launch')
895
-     * @return void
896
-     * @throws EE_Error
897
-     */
898
-    public function e_invoice_url($type = 'launch')
899
-    {
900
-        echo $this->invoice_url($type);
901
-    }
902
-
903
-
904
-    /**
905
-     * Echoes out payment_overview_url
906
-     */
907
-    public function e_payment_overview_url()
908
-    {
909
-        echo $this->payment_overview_url();
910
-    }
911
-
912
-
913
-    /**
914
-     * Gets the URL for the checkout payment options reg step
915
-     * with this registration's REG_url_link added as a query parameter
916
-     *
917
-     * @param bool $clear_session Set to true when you want to clear the session on revisiting the
918
-     *                            payment overview url.
919
-     * @return string
920
-     * @throws InvalidInterfaceException
921
-     * @throws InvalidDataTypeException
922
-     * @throws EE_Error
923
-     * @throws InvalidArgumentException
924
-     */
925
-    public function payment_overview_url($clear_session = false)
926
-    {
927
-        return add_query_arg(
928
-            (array) apply_filters(
929
-                'FHEE__EE_Registration__payment_overview_url__query_args',
930
-                array(
931
-                    'e_reg_url_link' => $this->reg_url_link(),
932
-                    'step'           => 'payment_options',
933
-                    'revisit'        => true,
934
-                    'clear_session'  => (bool) $clear_session,
935
-                ),
936
-                $this
937
-            ),
938
-            EE_Registry::instance()->CFG->core->reg_page_url()
939
-        );
940
-    }
941
-
942
-
943
-    /**
944
-     * Gets the URL for the checkout attendee information reg step
945
-     * with this registration's REG_url_link added as a query parameter
946
-     *
947
-     * @return string
948
-     * @throws InvalidInterfaceException
949
-     * @throws InvalidDataTypeException
950
-     * @throws EE_Error
951
-     * @throws InvalidArgumentException
952
-     */
953
-    public function edit_attendee_information_url()
954
-    {
955
-        return add_query_arg(
956
-            (array) apply_filters(
957
-                'FHEE__EE_Registration__edit_attendee_information_url__query_args',
958
-                array(
959
-                    'e_reg_url_link' => $this->reg_url_link(),
960
-                    'step'           => 'attendee_information',
961
-                    'revisit'        => true,
962
-                ),
963
-                $this
964
-            ),
965
-            EE_Registry::instance()->CFG->core->reg_page_url()
966
-        );
967
-    }
968
-
969
-
970
-    /**
971
-     * Simply generates and returns the appropriate admin_url link to edit this registration
972
-     *
973
-     * @return string
974
-     * @throws EE_Error
975
-     */
976
-    public function get_admin_edit_url()
977
-    {
978
-        return EEH_URL::add_query_args_and_nonce(
979
-            array(
980
-                'page'    => 'espresso_registrations',
981
-                'action'  => 'view_registration',
982
-                '_REG_ID' => $this->ID(),
983
-            ),
984
-            admin_url('admin.php')
985
-        );
986
-    }
987
-
988
-
989
-    /**
990
-     *    is_primary_registrant?
991
-     */
992
-    public function is_primary_registrant()
993
-    {
994
-        return $this->get('REG_count') === 1 ? true : false;
995
-    }
996
-
997
-
998
-    /**
999
-     * This returns the primary registration object for this registration group (which may be this object).
1000
-     *
1001
-     * @return EE_Registration
1002
-     * @throws EE_Error
1003
-     */
1004
-    public function get_primary_registration()
1005
-    {
1006
-        if ($this->is_primary_registrant()) {
1007
-            return $this;
1008
-        }
1009
-
1010
-        // k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1011
-        /** @var EE_Registration $primary_registrant */
1012
-        $primary_registrant = EEM_Registration::instance()->get_one(
1013
-            array(
1014
-                array(
1015
-                    'TXN_ID'    => $this->transaction_ID(),
1016
-                    'REG_count' => 1,
1017
-                ),
1018
-            )
1019
-        );
1020
-        return $primary_registrant;
1021
-    }
1022
-
1023
-
1024
-    /**
1025
-     *        get  Attendee Number
1026
-     *
1027
-     * @access        public
1028
-     */
1029
-    public function count()
1030
-    {
1031
-        return $this->get('REG_count');
1032
-    }
1033
-
1034
-
1035
-    /**
1036
-     *        get Group Size
1037
-     */
1038
-    public function group_size()
1039
-    {
1040
-        return $this->get('REG_group_size');
1041
-    }
1042
-
1043
-
1044
-    /**
1045
-     *        get Registration Date
1046
-     */
1047
-    public function date()
1048
-    {
1049
-        return $this->get('REG_date');
1050
-    }
1051
-
1052
-
1053
-    /**
1054
-     * gets a pretty date
1055
-     *
1056
-     * @param string $date_format
1057
-     * @param string $time_format
1058
-     * @return string
1059
-     * @throws EE_Error
1060
-     */
1061
-    public function pretty_date($date_format = null, $time_format = null)
1062
-    {
1063
-        return $this->get_datetime('REG_date', $date_format, $time_format);
1064
-    }
1065
-
1066
-
1067
-    /**
1068
-     * final_price
1069
-     * the registration's share of the transaction total, so that the
1070
-     * sum of all the transaction's REG_final_prices equal the transaction's total
1071
-     *
1072
-     * @return float
1073
-     * @throws EE_Error
1074
-     */
1075
-    public function final_price()
1076
-    {
1077
-        return $this->get('REG_final_price');
1078
-    }
1079
-
1080
-
1081
-    /**
1082
-     * pretty_final_price
1083
-     *  final price as formatted string, with correct decimal places and currency symbol
1084
-     *
1085
-     * @return string
1086
-     * @throws EE_Error
1087
-     */
1088
-    public function pretty_final_price()
1089
-    {
1090
-        return $this->get_pretty('REG_final_price');
1091
-    }
1092
-
1093
-
1094
-    /**
1095
-     * get paid (yeah)
1096
-     *
1097
-     * @return float
1098
-     * @throws EE_Error
1099
-     */
1100
-    public function paid()
1101
-    {
1102
-        return $this->get('REG_paid');
1103
-    }
1104
-
1105
-
1106
-    /**
1107
-     * pretty_paid
1108
-     *
1109
-     * @return float
1110
-     * @throws EE_Error
1111
-     */
1112
-    public function pretty_paid()
1113
-    {
1114
-        return $this->get_pretty('REG_paid');
1115
-    }
1116
-
1117
-
1118
-    /**
1119
-     * owes_monies_and_can_pay
1120
-     * whether or not this registration has monies owing and it's' status allows payment
1121
-     *
1122
-     * @param array $requires_payment
1123
-     * @return bool
1124
-     * @throws EE_Error
1125
-     */
1126
-    public function owes_monies_and_can_pay($requires_payment = array())
1127
-    {
1128
-        // these reg statuses require payment (if event is not free)
1129
-        $requires_payment = ! empty($requires_payment)
1130
-            ? $requires_payment
1131
-            : EEM_Registration::reg_statuses_that_allow_payment();
1132
-        if (in_array($this->status_ID(), $requires_payment) &&
1133
-            $this->final_price() != 0 &&
1134
-            $this->final_price() != $this->paid()
1135
-        ) {
1136
-            return true;
1137
-        } else {
1138
-            return false;
1139
-        }
1140
-    }
1141
-
1142
-
1143
-    /**
1144
-     * Prints out the return value of $this->pretty_status()
1145
-     *
1146
-     * @param bool $show_icons
1147
-     * @return void
1148
-     * @throws EE_Error
1149
-     */
1150
-    public function e_pretty_status($show_icons = false)
1151
-    {
1152
-        echo $this->pretty_status($show_icons);
1153
-    }
1154
-
1155
-
1156
-    /**
1157
-     * Returns a nice version of the status for displaying to customers
1158
-     *
1159
-     * @param bool $show_icons
1160
-     * @return string
1161
-     * @throws EE_Error
1162
-     */
1163
-    public function pretty_status($show_icons = false)
1164
-    {
1165
-        $status = EEM_Status::instance()->localized_status(
1166
-            array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1167
-            false,
1168
-            'sentence'
1169
-        );
1170
-        $icon = '';
1171
-        switch ($this->status_ID()) {
1172
-            case EEM_Registration::status_id_approved:
1173
-                $icon = $show_icons
1174
-                    ? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1175
-                    : '';
1176
-                break;
1177
-            case EEM_Registration::status_id_pending_payment:
1178
-                $icon = $show_icons
1179
-                    ? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1180
-                    : '';
1181
-                break;
1182
-            case EEM_Registration::status_id_not_approved:
1183
-                $icon = $show_icons
1184
-                    ? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1185
-                    : '';
1186
-                break;
1187
-            case EEM_Registration::status_id_cancelled:
1188
-                $icon = $show_icons
1189
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1190
-                    : '';
1191
-                break;
1192
-            case EEM_Registration::status_id_incomplete:
1193
-                $icon = $show_icons
1194
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1195
-                    : '';
1196
-                break;
1197
-            case EEM_Registration::status_id_declined:
1198
-                $icon = $show_icons
1199
-                    ? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1200
-                    : '';
1201
-                break;
1202
-            case EEM_Registration::status_id_wait_list:
1203
-                $icon = $show_icons
1204
-                    ? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1205
-                    : '';
1206
-                break;
1207
-        }
1208
-        return $icon . $status[ $this->status_ID() ];
1209
-    }
1210
-
1211
-
1212
-    /**
1213
-     *        get Attendee Is Going
1214
-     */
1215
-    public function att_is_going()
1216
-    {
1217
-        return $this->get('REG_att_is_going');
1218
-    }
1219
-
1220
-
1221
-    /**
1222
-     * Gets related answers
1223
-     *
1224
-     * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1225
-     * @return EE_Answer[]
1226
-     * @throws EE_Error
1227
-     */
1228
-    public function answers($query_params = null)
1229
-    {
1230
-        return $this->get_many_related('Answer', $query_params);
1231
-    }
1232
-
1233
-
1234
-    /**
1235
-     * Gets the registration's answer value to the specified question
1236
-     * (either the question's ID or a question object)
1237
-     *
1238
-     * @param EE_Question|int $question
1239
-     * @param bool            $pretty_value
1240
-     * @return array|string if pretty_value= true, the result will always be a string
1241
-     * (because the answer might be an array of answer values, so passing pretty_value=true
1242
-     * will convert it into some kind of string)
1243
-     * @throws EE_Error
1244
-     */
1245
-    public function answer_value_to_question($question, $pretty_value = true)
1246
-    {
1247
-        $question_id = EEM_Question::instance()->ensure_is_ID($question);
1248
-        return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1249
-    }
1250
-
1251
-
1252
-    /**
1253
-     * question_groups
1254
-     * returns an array of EE_Question_Group objects for this registration
1255
-     *
1256
-     * @return EE_Question_Group[]
1257
-     * @throws EE_Error
1258
-     * @throws InvalidArgumentException
1259
-     * @throws InvalidDataTypeException
1260
-     * @throws InvalidInterfaceException
1261
-     * @throws ReflectionException
1262
-     */
1263
-    public function question_groups()
1264
-    {
1265
-        return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1266
-    }
1267
-
1268
-
1269
-    /**
1270
-     * count_question_groups
1271
-     * returns a count of the number of EE_Question_Group objects for this registration
1272
-     *
1273
-     * @return int
1274
-     * @throws EE_Error
1275
-     * @throws EntityNotFoundException
1276
-     * @throws InvalidArgumentException
1277
-     * @throws InvalidDataTypeException
1278
-     * @throws InvalidInterfaceException
1279
-     * @throws ReflectionException
1280
-     */
1281
-    public function count_question_groups()
1282
-    {
1283
-        return EEM_Event::instance()->count_related(
1284
-            $this->event_ID(),
1285
-            'Question_Group',
1286
-            [
1287
-                [
1288
-                    'Event_Question_Group.'
1289
-                    . EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1290
-                ]
1291
-            ]
1292
-        );
1293
-    }
1294
-
1295
-
1296
-    /**
1297
-     * Returns the registration date in the 'standard' string format
1298
-     * (function may be improved in the future to allow for different formats and timezones)
1299
-     *
1300
-     * @return string
1301
-     * @throws EE_Error
1302
-     */
1303
-    public function reg_date()
1304
-    {
1305
-        return $this->get_datetime('REG_date');
1306
-    }
1307
-
1308
-
1309
-    /**
1310
-     * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1311
-     * the ticket this registration purchased, or the datetime they have registered
1312
-     * to attend)
1313
-     *
1314
-     * @return EE_Datetime_Ticket
1315
-     * @throws EE_Error
1316
-     */
1317
-    public function datetime_ticket()
1318
-    {
1319
-        return $this->get_first_related('Datetime_Ticket');
1320
-    }
1321
-
1322
-
1323
-    /**
1324
-     * Sets the registration's datetime_ticket.
1325
-     *
1326
-     * @param EE_Datetime_Ticket $datetime_ticket
1327
-     * @return EE_Datetime_Ticket
1328
-     * @throws EE_Error
1329
-     */
1330
-    public function set_datetime_ticket($datetime_ticket)
1331
-    {
1332
-        return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1333
-    }
1334
-
1335
-    /**
1336
-     * Gets deleted
1337
-     *
1338
-     * @return bool
1339
-     * @throws EE_Error
1340
-     */
1341
-    public function deleted()
1342
-    {
1343
-        return $this->get('REG_deleted');
1344
-    }
1345
-
1346
-    /**
1347
-     * Sets deleted
1348
-     *
1349
-     * @param boolean $deleted
1350
-     * @return bool
1351
-     * @throws EE_Error
1352
-     * @throws RuntimeException
1353
-     */
1354
-    public function set_deleted($deleted)
1355
-    {
1356
-        if ($deleted) {
1357
-            $this->delete();
1358
-        } else {
1359
-            $this->restore();
1360
-        }
1361
-    }
1362
-
1363
-
1364
-    /**
1365
-     * Get the status object of this object
1366
-     *
1367
-     * @return EE_Status
1368
-     * @throws EE_Error
1369
-     */
1370
-    public function status_obj()
1371
-    {
1372
-        return $this->get_first_related('Status');
1373
-    }
1374
-
1375
-
1376
-    /**
1377
-     * Returns the number of times this registration has checked into any of the datetimes
1378
-     * its available for
1379
-     *
1380
-     * @return int
1381
-     * @throws EE_Error
1382
-     */
1383
-    public function count_checkins()
1384
-    {
1385
-        return $this->get_model()->count_related($this, 'Checkin');
1386
-    }
1387
-
1388
-
1389
-    /**
1390
-     * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1391
-     * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1392
-     *
1393
-     * @return int
1394
-     * @throws EE_Error
1395
-     */
1396
-    public function count_checkins_not_checkedout()
1397
-    {
1398
-        return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1399
-    }
1400
-
1401
-
1402
-    /**
1403
-     * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1404
-     *
1405
-     * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1406
-     * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1407
-     *                                          consider registration status as well as datetime access.
1408
-     * @return bool
1409
-     * @throws EE_Error
1410
-     */
1411
-    public function can_checkin($DTT_OR_ID, $check_approved = true)
1412
-    {
1413
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1414
-
1415
-        // first check registration status
1416
-        if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1417
-            return false;
1418
-        }
1419
-        // is there a datetime ticket that matches this dtt_ID?
1420
-        if (! (EEM_Datetime_Ticket::instance()->exists(
1421
-            array(
1422
-                array(
1423
-                    'TKT_ID' => $this->get('TKT_ID'),
1424
-                    'DTT_ID' => $DTT_ID,
1425
-                ),
1426
-            )
1427
-        ))
1428
-        ) {
1429
-            return false;
1430
-        }
1431
-
1432
-        // final check is against TKT_uses
1433
-        return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1434
-    }
1435
-
1436
-
1437
-    /**
1438
-     * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1439
-     * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1440
-     * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1441
-     * then return false.  Otherwise return true.
1442
-     *
1443
-     * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1444
-     * @return bool true means can checkin.  false means cannot checkin.
1445
-     * @throws EE_Error
1446
-     */
1447
-    public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1448
-    {
1449
-        $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1450
-
1451
-        if (! $DTT_ID) {
1452
-            return false;
1453
-        }
1454
-
1455
-        $max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1456
-
1457
-        // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1458
-        // check-in or not.
1459
-        if (! $max_uses || $max_uses === EE_INF) {
1460
-            return true;
1461
-        }
1462
-
1463
-        // does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1464
-        // go ahead and toggle.
1465
-        if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1466
-            return true;
1467
-        }
1468
-
1469
-        // made it here so the last check is whether the number of checkins per unique datetime on this registration
1470
-        // disallows further check-ins.
1471
-        $count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1472
-            array(
1473
-                array(
1474
-                    'REG_ID' => $this->ID(),
1475
-                    'CHK_in' => true,
1476
-                ),
1477
-            ),
1478
-            'DTT_ID',
1479
-            true
1480
-        );
1481
-        // checkins have already reached their max number of uses
1482
-        // so registrant can NOT checkin
1483
-        if ($count_unique_dtt_checkins >= $max_uses) {
1484
-            EE_Error::add_error(
1485
-                esc_html__(
1486
-                    'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1487
-                    'event_espresso'
1488
-                ),
1489
-                __FILE__,
1490
-                __FUNCTION__,
1491
-                __LINE__
1492
-            );
1493
-            return false;
1494
-        }
1495
-        return true;
1496
-    }
1497
-
1498
-
1499
-    /**
1500
-     * toggle Check-in status for this registration
1501
-     * Check-ins are toggled in the following order:
1502
-     * never checked in -> checked in
1503
-     * checked in -> checked out
1504
-     * checked out -> checked in
1505
-     *
1506
-     * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1507
-     *                      If not included or null, then it is assumed latest datetime is being toggled.
1508
-     * @param bool $verify  If true then can_checkin() is used to verify whether the person
1509
-     *                      can be checked in or not.  Otherwise this forces change in checkin status.
1510
-     * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1511
-     * @throws EE_Error
1512
-     */
1513
-    public function toggle_checkin_status($DTT_ID = null, $verify = false)
1514
-    {
1515
-        if (empty($DTT_ID)) {
1516
-            $datetime = $this->get_latest_related_datetime();
1517
-            $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1518
-            // verify the registration can checkin for the given DTT_ID
1519
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1520
-            EE_Error::add_error(
1521
-                sprintf(
1522
-                    esc_html__(
1523
-                        'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1524
-                        'event_espresso'
1525
-                    ),
1526
-                    $this->ID(),
1527
-                    $DTT_ID
1528
-                ),
1529
-                __FILE__,
1530
-                __FUNCTION__,
1531
-                __LINE__
1532
-            );
1533
-            return false;
1534
-        }
1535
-        $status_paths = array(
1536
-            EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1537
-            EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1538
-            EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1539
-        );
1540
-        // start by getting the current status so we know what status we'll be changing to.
1541
-        $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1542
-        $status_to = $status_paths[ $cur_status ];
1543
-        // database only records true for checked IN or false for checked OUT
1544
-        // no record ( null ) means checked in NEVER, but we obviously don't save that
1545
-        $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1546
-        // add relation - note Check-ins are always creating new rows
1547
-        // because we are keeping track of Check-ins over time.
1548
-        // Eventually we'll probably want to show a list table
1549
-        // for the individual Check-ins so that they can be managed.
1550
-        $checkin = EE_Checkin::new_instance(
1551
-            array(
1552
-                'REG_ID' => $this->ID(),
1553
-                'DTT_ID' => $DTT_ID,
1554
-                'CHK_in' => $new_status,
1555
-            )
1556
-        );
1557
-        // if the record could not be saved then return false
1558
-        if ($checkin->save() === 0) {
1559
-            if (WP_DEBUG) {
1560
-                global $wpdb;
1561
-                $error = sprintf(
1562
-                    esc_html__(
1563
-                        'Registration check in update failed because of the following database error: %1$s%2$s',
1564
-                        'event_espresso'
1565
-                    ),
1566
-                    '<br />',
1567
-                    $wpdb->last_error
1568
-                );
1569
-            } else {
1570
-                $error = esc_html__(
1571
-                    'Registration check in update failed because of an unknown database error',
1572
-                    'event_espresso'
1573
-                );
1574
-            }
1575
-            EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1576
-            return false;
1577
-        }
1578
-        return $status_to;
1579
-    }
1580
-
1581
-
1582
-    /**
1583
-     * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1584
-     * "Latest" is defined by the `DTT_EVT_start` column.
1585
-     *
1586
-     * @return EE_Datetime|null
1587
-     * @throws EE_Error
1588
-     */
1589
-    public function get_latest_related_datetime()
1590
-    {
1591
-        return EEM_Datetime::instance()->get_one(
1592
-            array(
1593
-                array(
1594
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1595
-                ),
1596
-                'order_by' => array('DTT_EVT_start' => 'DESC'),
1597
-            )
1598
-        );
1599
-    }
1600
-
1601
-
1602
-    /**
1603
-     * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1604
-     * "Earliest" is defined by the `DTT_EVT_start` column.
1605
-     *
1606
-     * @throws EE_Error
1607
-     */
1608
-    public function get_earliest_related_datetime()
1609
-    {
1610
-        return EEM_Datetime::instance()->get_one(
1611
-            array(
1612
-                array(
1613
-                    'Ticket.Registration.REG_ID' => $this->ID(),
1614
-                ),
1615
-                'order_by' => array('DTT_EVT_start' => 'ASC'),
1616
-            )
1617
-        );
1618
-    }
1619
-
1620
-
1621
-    /**
1622
-     * This method simply returns the check-in status for this registration and the given datetime.
1623
-     * If neither the datetime nor the checkin values are provided as arguments,
1624
-     * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1625
-     *
1626
-     * @param  int       $DTT_ID  The ID of the datetime we're checking against
1627
-     *                            (if empty we'll get the primary datetime for
1628
-     *                            this registration (via event) and use it's ID);
1629
-     * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1630
-     *
1631
-     * @return int                Integer representing Check-in status.
1632
-     * @throws EE_Error
1633
-     */
1634
-    public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1635
-    {
1636
-        $checkin_query_params = array(
1637
-            'order_by' => array('CHK_timestamp' => 'DESC'),
1638
-        );
1639
-
1640
-        if ($DTT_ID > 0) {
1641
-            $checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1642
-        }
1643
-
1644
-        // get checkin object (if exists)
1645
-        $checkin = $checkin instanceof EE_Checkin
1646
-            ? $checkin
1647
-            : $this->get_first_related('Checkin', $checkin_query_params);
1648
-        if ($checkin instanceof EE_Checkin) {
1649
-            if ($checkin->get('CHK_in')) {
1650
-                return EE_Checkin::status_checked_in; // checked in
1651
-            }
1652
-            return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1653
-        }
1654
-        return EE_Checkin::status_checked_never; // never been checked in
1655
-    }
1656
-
1657
-
1658
-    /**
1659
-     * This method returns a localized message for the toggled Check-in message.
1660
-     *
1661
-     * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1662
-     *                     then it is assumed Check-in for primary datetime was toggled.
1663
-     * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1664
-     *                     message can be customized with the attendee name.
1665
-     * @return string internationalized message
1666
-     * @throws EE_Error
1667
-     */
1668
-    public function get_checkin_msg($DTT_ID, $error = false)
1669
-    {
1670
-        // let's get the attendee first so we can include the name of the attendee
1671
-        $attendee = $this->get_first_related('Attendee');
1672
-        if ($attendee instanceof EE_Attendee) {
1673
-            if ($error) {
1674
-                return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1675
-            }
1676
-            $cur_status = $this->check_in_status_for_datetime($DTT_ID);
1677
-            // what is the status message going to be?
1678
-            switch ($cur_status) {
1679
-                case EE_Checkin::status_checked_never:
1680
-                    return sprintf(
1681
-                        __("%s has been removed from Check-in records", "event_espresso"),
1682
-                        $attendee->full_name()
1683
-                    );
1684
-                    break;
1685
-                case EE_Checkin::status_checked_in:
1686
-                    return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1687
-                    break;
1688
-                case EE_Checkin::status_checked_out:
1689
-                    return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1690
-                    break;
1691
-            }
1692
-        }
1693
-        return esc_html__("The check-in status could not be determined.", "event_espresso");
1694
-    }
1695
-
1696
-
1697
-    /**
1698
-     * Returns the related EE_Transaction to this registration
1699
-     *
1700
-     * @return EE_Transaction
1701
-     * @throws EE_Error
1702
-     * @throws EntityNotFoundException
1703
-     */
1704
-    public function transaction()
1705
-    {
1706
-        $transaction = $this->get_first_related('Transaction');
1707
-        if (! $transaction instanceof \EE_Transaction) {
1708
-            throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1709
-        }
1710
-        return $transaction;
1711
-    }
1712
-
1713
-
1714
-    /**
1715
-     *        get Registration Code
1716
-     */
1717
-    public function reg_code()
1718
-    {
1719
-        return $this->get('REG_code');
1720
-    }
1721
-
1722
-
1723
-    /**
1724
-     *        get Transaction ID
1725
-     */
1726
-    public function transaction_ID()
1727
-    {
1728
-        return $this->get('TXN_ID');
1729
-    }
1730
-
1731
-
1732
-    /**
1733
-     * @return int
1734
-     * @throws EE_Error
1735
-     */
1736
-    public function ticket_ID()
1737
-    {
1738
-        return $this->get('TKT_ID');
1739
-    }
1740
-
1741
-
1742
-    /**
1743
-     *        Set Registration Code
1744
-     *
1745
-     * @access    public
1746
-     * @param    string  $REG_code Registration Code
1747
-     * @param    boolean $use_default
1748
-     * @throws EE_Error
1749
-     */
1750
-    public function set_reg_code($REG_code, $use_default = false)
1751
-    {
1752
-        if (empty($REG_code)) {
1753
-            EE_Error::add_error(
1754
-                esc_html__('REG_code can not be empty.', 'event_espresso'),
1755
-                __FILE__,
1756
-                __FUNCTION__,
1757
-                __LINE__
1758
-            );
1759
-            return;
1760
-        }
1761
-        if (! $this->reg_code()) {
1762
-            parent::set('REG_code', $REG_code, $use_default);
1763
-        } else {
1764
-            EE_Error::doing_it_wrong(
1765
-                __CLASS__ . '::' . __FUNCTION__,
1766
-                esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1767
-                '4.6.0'
1768
-            );
1769
-        }
1770
-    }
1771
-
1772
-
1773
-    /**
1774
-     * Returns all other registrations in the same group as this registrant who have the same ticket option.
1775
-     * Note, if you want to just get all registrations in the same transaction (group), use:
1776
-     *    $registration->transaction()->registrations();
1777
-     *
1778
-     * @since 4.5.0
1779
-     * @return EE_Registration[] or empty array if this isn't a group registration.
1780
-     * @throws EE_Error
1781
-     */
1782
-    public function get_all_other_registrations_in_group()
1783
-    {
1784
-        if ($this->group_size() < 2) {
1785
-            return array();
1786
-        }
1787
-
1788
-        $query[0] = array(
1789
-            'TXN_ID' => $this->transaction_ID(),
1790
-            'REG_ID' => array('!=', $this->ID()),
1791
-            'TKT_ID' => $this->ticket_ID(),
1792
-        );
1793
-        /** @var EE_Registration[] $registrations */
1794
-        $registrations = $this->get_model()->get_all($query);
1795
-        return $registrations;
1796
-    }
1797
-
1798
-    /**
1799
-     * Return the link to the admin details for the object.
1800
-     *
1801
-     * @return string
1802
-     * @throws EE_Error
1803
-     */
1804
-    public function get_admin_details_link()
1805
-    {
1806
-        EE_Registry::instance()->load_helper('URL');
1807
-        return EEH_URL::add_query_args_and_nonce(
1808
-            array(
1809
-                'page'    => 'espresso_registrations',
1810
-                'action'  => 'view_registration',
1811
-                '_REG_ID' => $this->ID(),
1812
-            ),
1813
-            admin_url('admin.php')
1814
-        );
1815
-    }
1816
-
1817
-    /**
1818
-     * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1819
-     *
1820
-     * @return string
1821
-     * @throws EE_Error
1822
-     */
1823
-    public function get_admin_edit_link()
1824
-    {
1825
-        return $this->get_admin_details_link();
1826
-    }
1827
-
1828
-    /**
1829
-     * Returns the link to a settings page for the object.
1830
-     *
1831
-     * @return string
1832
-     * @throws EE_Error
1833
-     */
1834
-    public function get_admin_settings_link()
1835
-    {
1836
-        return $this->get_admin_details_link();
1837
-    }
1838
-
1839
-    /**
1840
-     * Returns the link to the "overview" for the object (typically the "list table" view).
1841
-     *
1842
-     * @return string
1843
-     */
1844
-    public function get_admin_overview_link()
1845
-    {
1846
-        EE_Registry::instance()->load_helper('URL');
1847
-        return EEH_URL::add_query_args_and_nonce(
1848
-            array(
1849
-                'page' => 'espresso_registrations',
1850
-            ),
1851
-            admin_url('admin.php')
1852
-        );
1853
-    }
1854
-
1855
-
1856
-    /**
1857
-     * @param array $query_params
1858
-     *
1859
-     * @return \EE_Registration[]
1860
-     * @throws EE_Error
1861
-     */
1862
-    public function payments($query_params = array())
1863
-    {
1864
-        return $this->get_many_related('Payment', $query_params);
1865
-    }
1866
-
1867
-
1868
-    /**
1869
-     * @param array $query_params
1870
-     *
1871
-     * @return \EE_Registration_Payment[]
1872
-     * @throws EE_Error
1873
-     */
1874
-    public function registration_payments($query_params = array())
1875
-    {
1876
-        return $this->get_many_related('Registration_Payment', $query_params);
1877
-    }
1878
-
1879
-
1880
-    /**
1881
-     * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1882
-     * Note: if there are no payments on the registration there will be no payment method returned.
1883
-     *
1884
-     * @return EE_Payment_Method|null
1885
-     */
1886
-    public function payment_method()
1887
-    {
1888
-        return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1889
-    }
1890
-
1891
-
1892
-    /**
1893
-     * @return \EE_Line_Item
1894
-     * @throws EntityNotFoundException
1895
-     * @throws EE_Error
1896
-     */
1897
-    public function ticket_line_item()
1898
-    {
1899
-        $ticket = $this->ticket();
1900
-        $transaction = $this->transaction();
1901
-        $line_item = null;
1902
-        $ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1903
-            $transaction->total_line_item(),
1904
-            'Ticket',
1905
-            array($ticket->ID())
1906
-        );
1907
-        foreach ($ticket_line_items as $ticket_line_item) {
1908
-            if ($ticket_line_item instanceof \EE_Line_Item
1909
-                && $ticket_line_item->OBJ_type() === 'Ticket'
1910
-                && $ticket_line_item->OBJ_ID() === $ticket->ID()
1911
-            ) {
1912
-                $line_item = $ticket_line_item;
1913
-                break;
1914
-            }
1915
-        }
1916
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1917
-            throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1918
-        }
1919
-        return $line_item;
1920
-    }
1921
-
1922
-
1923
-    /**
1924
-     * Soft Deletes this model object.
1925
-     *
1926
-     * @return boolean | int
1927
-     * @throws RuntimeException
1928
-     * @throws EE_Error
1929
-     */
1930
-    public function delete()
1931
-    {
1932
-        if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1933
-            $this->set_status(EEM_Registration::status_id_cancelled);
1934
-        }
1935
-        return parent::delete();
1936
-    }
1937
-
1938
-
1939
-    /**
1940
-     * Restores whatever the previous status was on a registration before it was trashed (if possible)
1941
-     *
1942
-     * @throws EE_Error
1943
-     * @throws RuntimeException
1944
-     */
1945
-    public function restore()
1946
-    {
1947
-        $previous_status = $this->get_extra_meta(
1948
-            EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1949
-            true,
1950
-            EEM_Registration::status_id_cancelled
1951
-        );
1952
-        if ($previous_status) {
1953
-            $this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1954
-            $this->set_status($previous_status);
1955
-        }
1956
-        return parent::restore();
1957
-    }
1958
-
1959
-
1960
-    /**
1961
-     * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1962
-     *
1963
-     * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1964
-     *                                           depending on whether the reg status changes to or from "Approved"
1965
-     * @return boolean whether the Registration status was updated
1966
-     * @throws EE_Error
1967
-     * @throws RuntimeException
1968
-     */
1969
-    public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1970
-    {
1971
-        $paid = $this->paid();
1972
-        $price = $this->final_price();
1973
-        switch (true) {
1974
-            // overpaid or paid
1975
-            case EEH_Money::compare_floats($paid, $price, '>'):
1976
-            case EEH_Money::compare_floats($paid, $price):
1977
-                $new_status = EEM_Registration::status_id_approved;
1978
-                break;
1979
-            //  underpaid
1980
-            case EEH_Money::compare_floats($paid, $price, '<'):
1981
-                $new_status = EEM_Registration::status_id_pending_payment;
1982
-                break;
1983
-            // uhhh Houston...
1984
-            default:
1985
-                throw new RuntimeException(
1986
-                    esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
1987
-                );
1988
-        }
1989
-        if ($new_status !== $this->status_ID()) {
1990
-            if ($trigger_set_status_logic) {
1991
-                return $this->set_status($new_status);
1992
-            }
1993
-            parent::set('STS_ID', $new_status);
1994
-            return true;
1995
-        }
1996
-        return false;
1997
-    }
1998
-
1999
-
2000
-    /*************************** DEPRECATED ***************************/
2001
-
2002
-
2003
-    /**
2004
-     * @deprecated
2005
-     * @since     4.7.0
2006
-     * @access    public
2007
-     */
2008
-    public function price_paid()
2009
-    {
2010
-        EE_Error::doing_it_wrong(
2011
-            'EE_Registration::price_paid()',
2012
-            esc_html__(
2013
-                'This method is deprecated, please use EE_Registration::final_price() instead.',
2014
-                'event_espresso'
2015
-            ),
2016
-            '4.7.0'
2017
-        );
2018
-        return $this->final_price();
2019
-    }
2020
-
2021
-
2022
-    /**
2023
-     * @deprecated
2024
-     * @since     4.7.0
2025
-     * @access    public
2026
-     * @param    float $REG_final_price
2027
-     * @throws EE_Error
2028
-     * @throws RuntimeException
2029
-     */
2030
-    public function set_price_paid($REG_final_price = 0.00)
2031
-    {
2032
-        EE_Error::doing_it_wrong(
2033
-            'EE_Registration::set_price_paid()',
2034
-            esc_html__(
2035
-                'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2036
-                'event_espresso'
2037
-            ),
2038
-            '4.7.0'
2039
-        );
2040
-        $this->set_final_price($REG_final_price);
2041
-    }
2042
-
2043
-
2044
-    /**
2045
-     * @deprecated
2046
-     * @since 4.7.0
2047
-     * @return string
2048
-     * @throws EE_Error
2049
-     */
2050
-    public function pretty_price_paid()
2051
-    {
2052
-        EE_Error::doing_it_wrong(
2053
-            'EE_Registration::pretty_price_paid()',
2054
-            esc_html__(
2055
-                'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2056
-                'event_espresso'
2057
-            ),
2058
-            '4.7.0'
2059
-        );
2060
-        return $this->pretty_final_price();
2061
-    }
2062
-
2063
-
2064
-    /**
2065
-     * Gets the primary datetime related to this registration via the related Event to this registration
2066
-     *
2067
-     * @deprecated 4.9.17
2068
-     * @return EE_Datetime
2069
-     * @throws EE_Error
2070
-     * @throws EntityNotFoundException
2071
-     */
2072
-    public function get_related_primary_datetime()
2073
-    {
2074
-        EE_Error::doing_it_wrong(
2075
-            __METHOD__,
2076
-            esc_html__(
2077
-                'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2078
-                'event_espresso'
2079
-            ),
2080
-            '4.9.17',
2081
-            '5.0.0'
2082
-        );
2083
-        return $this->event()->primary_datetime();
2084
-    }
2085
-
2086
-    public function name()
2087
-    {
2088
-        $attendee = $this->attendee();
2089
-        if($attendee instanceof EE_Attendee){
2090
-            $attendee_name = $attendee->full_name();
2091
-        } else {
2092
-            $attendee_name = esc_html__('Unknown', 'event_espresso');
2093
-        }
2094
-        return esc_html(
2095
-            sprintf(
2096
-                // translators: 1: registration code, 2: number, 3: group size, 4: attendee name.
2097
-                __('Registration with code "%1$s", %2$d of %3$d for %4$s', 'event_espresso'),
2098
-                $this->reg_code(),
2099
-                $this->count(),
2100
-                $this->group_size(),
2101
-                $attendee_name
2102
-            )
2103
-        );
2104
-    }
20
+	/**
21
+	 * Used to reference when a registration has never been checked in.
22
+	 *
23
+	 * @deprecated use \EE_Checkin::status_checked_never instead
24
+	 * @type int
25
+	 */
26
+	const checkin_status_never = 2;
27
+
28
+	/**
29
+	 * Used to reference when a registration has been checked in.
30
+	 *
31
+	 * @deprecated use \EE_Checkin::status_checked_in instead
32
+	 * @type int
33
+	 */
34
+	const checkin_status_in = 1;
35
+
36
+
37
+	/**
38
+	 * Used to reference when a registration has been checked out.
39
+	 *
40
+	 * @deprecated use \EE_Checkin::status_checked_out instead
41
+	 * @type int
42
+	 */
43
+	const checkin_status_out = 0;
44
+
45
+
46
+	/**
47
+	 * extra meta key for tracking reg status os trashed registrations
48
+	 *
49
+	 * @type string
50
+	 */
51
+	const PRE_TRASH_REG_STATUS_KEY = 'pre_trash_registration_status';
52
+
53
+
54
+	/**
55
+	 * extra meta key for tracking if registration has reserved ticket
56
+	 *
57
+	 * @type string
58
+	 */
59
+	const HAS_RESERVED_TICKET_KEY = 'has_reserved_ticket';
60
+
61
+
62
+	/**
63
+	 * @param array  $props_n_values          incoming values
64
+	 * @param string $timezone                incoming timezone (if not set the timezone set for the website will be
65
+	 *                                        used.)
66
+	 * @param array  $date_formats            incoming date_formats in an array where the first value is the
67
+	 *                                        date_format and the second value is the time format
68
+	 * @return EE_Registration
69
+	 * @throws EE_Error
70
+	 */
71
+	public static function new_instance($props_n_values = array(), $timezone = null, $date_formats = array())
72
+	{
73
+		$has_object = parent::_check_for_object($props_n_values, __CLASS__, $timezone, $date_formats);
74
+		return $has_object ? $has_object : new self($props_n_values, false, $timezone, $date_formats);
75
+	}
76
+
77
+
78
+	/**
79
+	 * @param array  $props_n_values  incoming values from the database
80
+	 * @param string $timezone        incoming timezone as set by the model.  If not set the timezone for
81
+	 *                                the website will be used.
82
+	 * @return EE_Registration
83
+	 */
84
+	public static function new_instance_from_db($props_n_values = array(), $timezone = null)
85
+	{
86
+		return new self($props_n_values, true, $timezone);
87
+	}
88
+
89
+
90
+	/**
91
+	 *        Set Event ID
92
+	 *
93
+	 * @param        int $EVT_ID Event ID
94
+	 * @throws EE_Error
95
+	 * @throws RuntimeException
96
+	 */
97
+	public function set_event($EVT_ID = 0)
98
+	{
99
+		$this->set('EVT_ID', $EVT_ID);
100
+	}
101
+
102
+
103
+	/**
104
+	 * Overrides parent set() method so that all calls to set( 'REG_code', $REG_code ) OR set( 'STS_ID', $STS_ID ) can
105
+	 * be routed to internal methods
106
+	 *
107
+	 * @param string $field_name
108
+	 * @param mixed  $field_value
109
+	 * @param bool   $use_default
110
+	 * @throws EE_Error
111
+	 * @throws EntityNotFoundException
112
+	 * @throws InvalidArgumentException
113
+	 * @throws InvalidDataTypeException
114
+	 * @throws InvalidInterfaceException
115
+	 * @throws ReflectionException
116
+	 * @throws RuntimeException
117
+	 */
118
+	public function set($field_name, $field_value, $use_default = false)
119
+	{
120
+		switch ($field_name) {
121
+			case 'REG_code':
122
+				if (! empty($field_value) && $this->reg_code() === null) {
123
+					$this->set_reg_code($field_value, $use_default);
124
+				}
125
+				break;
126
+			case 'STS_ID':
127
+				$this->set_status($field_value, $use_default);
128
+				break;
129
+			default:
130
+				parent::set($field_name, $field_value, $use_default);
131
+		}
132
+	}
133
+
134
+
135
+	/**
136
+	 * Set Status ID
137
+	 * updates the registration status and ALSO...
138
+	 * calls reserve_registration_space() if the reg status changes TO approved from any other reg status
139
+	 * calls release_registration_space() if the reg status changes FROM approved to any other reg status
140
+	 *
141
+	 * @param string                $new_STS_ID
142
+	 * @param boolean               $use_default
143
+	 * @param ContextInterface|null $context
144
+	 * @return bool
145
+	 * @throws DomainException
146
+	 * @throws EE_Error
147
+	 * @throws EntityNotFoundException
148
+	 * @throws InvalidArgumentException
149
+	 * @throws InvalidDataTypeException
150
+	 * @throws InvalidInterfaceException
151
+	 * @throws ReflectionException
152
+	 * @throws RuntimeException
153
+	 * @throws UnexpectedEntityException
154
+	 */
155
+	public function set_status($new_STS_ID = null, $use_default = false, ContextInterface $context = null)
156
+	{
157
+		// get current REG_Status
158
+		$old_STS_ID = $this->status_ID();
159
+		// if status has changed
160
+		if ($old_STS_ID !== $new_STS_ID // and that status has actually changed
161
+			&& ! empty($old_STS_ID) // and that old status is actually set
162
+			&& ! empty($new_STS_ID) // as well as the new status
163
+			&& $this->ID() // ensure registration is in the db
164
+		) {
165
+			// update internal status first
166
+			parent::set('STS_ID', $new_STS_ID, $use_default);
167
+			// THEN handle other changes that occur when reg status changes
168
+			// TO approved
169
+			if ($new_STS_ID === EEM_Registration::status_id_approved) {
170
+				// reserve a space by incrementing ticket and datetime sold values
171
+				$this->reserveRegistrationSpace();
172
+				do_action('AHEE__EE_Registration__set_status__to_approved', $this, $old_STS_ID, $new_STS_ID, $context);
173
+				// OR FROM  approved
174
+			} elseif ($old_STS_ID === EEM_Registration::status_id_approved) {
175
+				// release a space by decrementing ticket and datetime sold values
176
+				$this->releaseRegistrationSpace();
177
+				do_action(
178
+					'AHEE__EE_Registration__set_status__from_approved',
179
+					$this,
180
+					$old_STS_ID,
181
+					$new_STS_ID,
182
+					$context
183
+				);
184
+			}
185
+			// update status
186
+			parent::set('STS_ID', $new_STS_ID, $use_default);
187
+			$this->updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, $context);
188
+			if ($this->statusChangeUpdatesTransaction($context)) {
189
+				$this->updateTransactionAfterStatusChange();
190
+			}
191
+			do_action('AHEE__EE_Registration__set_status__after_update', $this, $old_STS_ID, $new_STS_ID, $context);
192
+			return true;
193
+		}
194
+		// even though the old value matches the new value, it's still good to
195
+		// allow the parent set method to have a say
196
+		parent::set('STS_ID', $new_STS_ID, $use_default);
197
+		return true;
198
+	}
199
+
200
+
201
+	/**
202
+	 * update REGs and TXN when cancelled or declined registrations involved
203
+	 *
204
+	 * @param string                $new_STS_ID
205
+	 * @param string                $old_STS_ID
206
+	 * @param ContextInterface|null $context
207
+	 * @throws EE_Error
208
+	 * @throws InvalidArgumentException
209
+	 * @throws InvalidDataTypeException
210
+	 * @throws InvalidInterfaceException
211
+	 * @throws ReflectionException
212
+	 * @throws RuntimeException
213
+	 */
214
+	private function updateIfCanceledOrReinstated($new_STS_ID, $old_STS_ID, ContextInterface $context = null)
215
+	{
216
+		// these reg statuses should not be considered in any calculations involving monies owing
217
+		$closed_reg_statuses = EEM_Registration::closed_reg_statuses();
218
+		// true if registration has been cancelled or declined
219
+		$this->updateIfCanceled(
220
+			$closed_reg_statuses,
221
+			$new_STS_ID,
222
+			$old_STS_ID,
223
+			$context
224
+		);
225
+		$this->updateIfReinstated(
226
+			$closed_reg_statuses,
227
+			$new_STS_ID,
228
+			$old_STS_ID,
229
+			$context
230
+		);
231
+	}
232
+
233
+
234
+	/**
235
+	 * update REGs and TXN when cancelled or declined registrations involved
236
+	 *
237
+	 * @param array                 $closed_reg_statuses
238
+	 * @param string                $new_STS_ID
239
+	 * @param string                $old_STS_ID
240
+	 * @param ContextInterface|null $context
241
+	 * @throws EE_Error
242
+	 * @throws InvalidArgumentException
243
+	 * @throws InvalidDataTypeException
244
+	 * @throws InvalidInterfaceException
245
+	 * @throws ReflectionException
246
+	 * @throws RuntimeException
247
+	 */
248
+	private function updateIfCanceled(
249
+		array $closed_reg_statuses,
250
+		$new_STS_ID,
251
+		$old_STS_ID,
252
+		ContextInterface $context = null
253
+	) {
254
+		// true if registration has been cancelled or declined
255
+		if (in_array($new_STS_ID, $closed_reg_statuses, true)
256
+			&& ! in_array($old_STS_ID, $closed_reg_statuses, true)
257
+		) {
258
+			/** @type EE_Registration_Processor $registration_processor */
259
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
260
+			/** @type EE_Transaction_Processor $transaction_processor */
261
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
262
+			// cancelled or declined registration
263
+			$registration_processor->update_registration_after_being_canceled_or_declined(
264
+				$this,
265
+				$closed_reg_statuses
266
+			);
267
+			$transaction_processor->update_transaction_after_canceled_or_declined_registration(
268
+				$this,
269
+				$closed_reg_statuses,
270
+				false
271
+			);
272
+			do_action(
273
+				'AHEE__EE_Registration__set_status__canceled_or_declined',
274
+				$this,
275
+				$old_STS_ID,
276
+				$new_STS_ID,
277
+				$context
278
+			);
279
+			return;
280
+		}
281
+	}
282
+
283
+
284
+	/**
285
+	 * update REGs and TXN when cancelled or declined registrations involved
286
+	 *
287
+	 * @param array                 $closed_reg_statuses
288
+	 * @param string                $new_STS_ID
289
+	 * @param string                $old_STS_ID
290
+	 * @param ContextInterface|null $context
291
+	 * @throws EE_Error
292
+	 * @throws InvalidArgumentException
293
+	 * @throws InvalidDataTypeException
294
+	 * @throws InvalidInterfaceException
295
+	 * @throws ReflectionException
296
+	 */
297
+	private function updateIfReinstated(
298
+		array $closed_reg_statuses,
299
+		$new_STS_ID,
300
+		$old_STS_ID,
301
+		ContextInterface $context = null
302
+	) {
303
+		// true if reinstating cancelled or declined registration
304
+		if (in_array($old_STS_ID, $closed_reg_statuses, true)
305
+			&& ! in_array($new_STS_ID, $closed_reg_statuses, true)
306
+		) {
307
+			/** @type EE_Registration_Processor $registration_processor */
308
+			$registration_processor = EE_Registry::instance()->load_class('Registration_Processor');
309
+			/** @type EE_Transaction_Processor $transaction_processor */
310
+			$transaction_processor = EE_Registry::instance()->load_class('Transaction_Processor');
311
+			// reinstating cancelled or declined registration
312
+			$registration_processor->update_canceled_or_declined_registration_after_being_reinstated(
313
+				$this,
314
+				$closed_reg_statuses
315
+			);
316
+			$transaction_processor->update_transaction_after_reinstating_canceled_registration(
317
+				$this,
318
+				$closed_reg_statuses,
319
+				false
320
+			);
321
+			do_action(
322
+				'AHEE__EE_Registration__set_status__after_reinstated',
323
+				$this,
324
+				$old_STS_ID,
325
+				$new_STS_ID,
326
+				$context
327
+			);
328
+		}
329
+	}
330
+
331
+
332
+	/**
333
+	 * @param ContextInterface|null $context
334
+	 * @return bool
335
+	 */
336
+	private function statusChangeUpdatesTransaction(ContextInterface $context = null)
337
+	{
338
+		$contexts_that_do_not_update_transaction = (array) apply_filters(
339
+			'AHEE__EE_Registration__statusChangeUpdatesTransaction__contexts_that_do_not_update_transaction',
340
+			array('spco_reg_step_attendee_information_process_registrations'),
341
+			$context,
342
+			$this
343
+		);
344
+		return ! (
345
+			$context instanceof ContextInterface
346
+			&& in_array($context->slug(), $contexts_that_do_not_update_transaction, true)
347
+		);
348
+	}
349
+
350
+
351
+	/**
352
+	 * @throws EE_Error
353
+	 * @throws EntityNotFoundException
354
+	 * @throws InvalidArgumentException
355
+	 * @throws InvalidDataTypeException
356
+	 * @throws InvalidInterfaceException
357
+	 * @throws ReflectionException
358
+	 * @throws RuntimeException
359
+	 */
360
+	private function updateTransactionAfterStatusChange()
361
+	{
362
+		/** @type EE_Transaction_Payments $transaction_payments */
363
+		$transaction_payments = EE_Registry::instance()->load_class('Transaction_Payments');
364
+		$transaction_payments->recalculate_transaction_total($this->transaction(), false);
365
+		$this->transaction()->update_status_based_on_total_paid(true);
366
+	}
367
+
368
+
369
+	/**
370
+	 *        get Status ID
371
+	 */
372
+	public function status_ID()
373
+	{
374
+		return $this->get('STS_ID');
375
+	}
376
+
377
+
378
+	/**
379
+	 * Gets the ticket this registration is for
380
+	 *
381
+	 * @param boolean $include_archived whether to include archived tickets or not.
382
+	 *
383
+	 * @return EE_Ticket|EE_Base_Class
384
+	 * @throws EE_Error
385
+	 */
386
+	public function ticket($include_archived = true)
387
+	{
388
+		$query_params = array();
389
+		if ($include_archived) {
390
+			$query_params['default_where_conditions'] = 'none';
391
+		}
392
+		return $this->get_first_related('Ticket', $query_params);
393
+	}
394
+
395
+
396
+	/**
397
+	 * Gets the event this registration is for
398
+	 *
399
+	 * @return EE_Event
400
+	 * @throws EE_Error
401
+	 * @throws EntityNotFoundException
402
+	 */
403
+	public function event()
404
+	{
405
+		$event = $this->get_first_related('Event');
406
+		if (! $event instanceof \EE_Event) {
407
+			throw new EntityNotFoundException('Event ID', $this->event_ID());
408
+		}
409
+		return $event;
410
+	}
411
+
412
+
413
+	/**
414
+	 * Gets the "author" of the registration.  Note that for the purposes of registrations, the author will correspond
415
+	 * with the author of the event this registration is for.
416
+	 *
417
+	 * @since 4.5.0
418
+	 * @return int
419
+	 * @throws EE_Error
420
+	 * @throws EntityNotFoundException
421
+	 */
422
+	public function wp_user()
423
+	{
424
+		$event = $this->event();
425
+		if ($event instanceof EE_Event) {
426
+			return $event->wp_user();
427
+		}
428
+		return 0;
429
+	}
430
+
431
+
432
+	/**
433
+	 * increments this registration's related ticket sold and corresponding datetime sold values
434
+	 *
435
+	 * @return void
436
+	 * @throws DomainException
437
+	 * @throws EE_Error
438
+	 * @throws EntityNotFoundException
439
+	 * @throws InvalidArgumentException
440
+	 * @throws InvalidDataTypeException
441
+	 * @throws InvalidInterfaceException
442
+	 * @throws ReflectionException
443
+	 * @throws UnexpectedEntityException
444
+	 */
445
+	private function reserveRegistrationSpace()
446
+	{
447
+		// reserved ticket and datetime counts will be decremented as sold counts are incremented
448
+		// so stop tracking that this reg has a ticket reserved
449
+		$this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
450
+		$ticket = $this->ticket();
451
+		$ticket->increaseSold();
452
+		// possibly set event status to sold out
453
+		$this->event()->perform_sold_out_status_check();
454
+	}
455
+
456
+
457
+	/**
458
+	 * decrements (subtracts) this registration's related ticket sold and corresponding datetime sold values
459
+	 *
460
+	 * @return void
461
+	 * @throws DomainException
462
+	 * @throws EE_Error
463
+	 * @throws EntityNotFoundException
464
+	 * @throws InvalidArgumentException
465
+	 * @throws InvalidDataTypeException
466
+	 * @throws InvalidInterfaceException
467
+	 * @throws ReflectionException
468
+	 * @throws UnexpectedEntityException
469
+	 */
470
+	private function releaseRegistrationSpace()
471
+	{
472
+		$ticket = $this->ticket();
473
+		$ticket->decreaseSold();
474
+		// possibly change event status from sold out back to previous status
475
+		$this->event()->perform_sold_out_status_check();
476
+	}
477
+
478
+
479
+	/**
480
+	 * tracks this registration's ticket reservation in extra meta
481
+	 * and can increment related ticket reserved and corresponding datetime reserved values
482
+	 *
483
+	 * @param bool $update_ticket if true, will increment ticket and datetime reserved count
484
+	 * @return void
485
+	 * @throws EE_Error
486
+	 * @throws InvalidArgumentException
487
+	 * @throws InvalidDataTypeException
488
+	 * @throws InvalidInterfaceException
489
+	 * @throws ReflectionException
490
+	 */
491
+	public function reserve_ticket($update_ticket = false, $source = 'unknown')
492
+	{
493
+		// only reserve ticket if space is not currently reserved
494
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) !== true) {
495
+			$this->update_extra_meta('reserve_ticket', "{$this->ticket_ID()} from {$source}");
496
+			// IMPORTANT !!!
497
+			// although checking $update_ticket first would be more efficient,
498
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
499
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true)
500
+				&& $update_ticket
501
+			) {
502
+				$ticket = $this->ticket();
503
+				$ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
504
+				$ticket->save();
505
+			}
506
+		}
507
+	}
508
+
509
+
510
+	/**
511
+	 * stops tracking this registration's ticket reservation in extra meta
512
+	 * decrements (subtracts) related ticket reserved and corresponding datetime reserved values
513
+	 *
514
+	 * @param bool $update_ticket if true, will decrement ticket and datetime reserved count
515
+	 * @return void
516
+	 * @throws EE_Error
517
+	 * @throws InvalidArgumentException
518
+	 * @throws InvalidDataTypeException
519
+	 * @throws InvalidInterfaceException
520
+	 * @throws ReflectionException
521
+	 */
522
+	public function release_reserved_ticket($update_ticket = false, $source = 'unknown')
523
+	{
524
+		// only release ticket if space is currently reserved
525
+		if ((bool) $this->get_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, true) === true) {
526
+			$this->update_extra_meta('release_reserved_ticket', "{$this->ticket_ID()} from {$source}");
527
+			// IMPORTANT !!!
528
+			// although checking $update_ticket first would be more efficient,
529
+			// we NEED to ALWAYS call update_extra_meta(), which is why that is done first
530
+			if ($this->update_extra_meta(EE_Registration::HAS_RESERVED_TICKET_KEY, false)
531
+				&& $update_ticket
532
+			) {
533
+				$ticket = $this->ticket();
534
+				$ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
535
+			}
536
+		}
537
+	}
538
+
539
+
540
+	/**
541
+	 * Set Attendee ID
542
+	 *
543
+	 * @param        int $ATT_ID Attendee ID
544
+	 * @throws EE_Error
545
+	 * @throws RuntimeException
546
+	 */
547
+	public function set_attendee_id($ATT_ID = 0)
548
+	{
549
+		$this->set('ATT_ID', $ATT_ID);
550
+	}
551
+
552
+
553
+	/**
554
+	 *        Set Transaction ID
555
+	 *
556
+	 * @param        int $TXN_ID Transaction ID
557
+	 * @throws EE_Error
558
+	 * @throws RuntimeException
559
+	 */
560
+	public function set_transaction_id($TXN_ID = 0)
561
+	{
562
+		$this->set('TXN_ID', $TXN_ID);
563
+	}
564
+
565
+
566
+	/**
567
+	 *        Set Session
568
+	 *
569
+	 * @param    string $REG_session PHP Session ID
570
+	 * @throws EE_Error
571
+	 * @throws RuntimeException
572
+	 */
573
+	public function set_session($REG_session = '')
574
+	{
575
+		$this->set('REG_session', $REG_session);
576
+	}
577
+
578
+
579
+	/**
580
+	 *        Set Registration URL Link
581
+	 *
582
+	 * @param    string $REG_url_link Registration URL Link
583
+	 * @throws EE_Error
584
+	 * @throws RuntimeException
585
+	 */
586
+	public function set_reg_url_link($REG_url_link = '')
587
+	{
588
+		$this->set('REG_url_link', $REG_url_link);
589
+	}
590
+
591
+
592
+	/**
593
+	 *        Set Attendee Counter
594
+	 *
595
+	 * @param        int $REG_count Primary Attendee
596
+	 * @throws EE_Error
597
+	 * @throws RuntimeException
598
+	 */
599
+	public function set_count($REG_count = 1)
600
+	{
601
+		$this->set('REG_count', $REG_count);
602
+	}
603
+
604
+
605
+	/**
606
+	 *        Set Group Size
607
+	 *
608
+	 * @param        boolean $REG_group_size Group Registration
609
+	 * @throws EE_Error
610
+	 * @throws RuntimeException
611
+	 */
612
+	public function set_group_size($REG_group_size = false)
613
+	{
614
+		$this->set('REG_group_size', $REG_group_size);
615
+	}
616
+
617
+
618
+	/**
619
+	 *    is_not_approved -  convenience method that returns TRUE if REG status ID ==
620
+	 *    EEM_Registration::status_id_not_approved
621
+	 *
622
+	 * @return        boolean
623
+	 */
624
+	public function is_not_approved()
625
+	{
626
+		return $this->status_ID() == EEM_Registration::status_id_not_approved ? true : false;
627
+	}
628
+
629
+
630
+	/**
631
+	 *    is_pending_payment -  convenience method that returns TRUE if REG status ID ==
632
+	 *    EEM_Registration::status_id_pending_payment
633
+	 *
634
+	 * @return        boolean
635
+	 */
636
+	public function is_pending_payment()
637
+	{
638
+		return $this->status_ID() == EEM_Registration::status_id_pending_payment ? true : false;
639
+	}
640
+
641
+
642
+	/**
643
+	 *    is_approved -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_approved
644
+	 *
645
+	 * @return        boolean
646
+	 */
647
+	public function is_approved()
648
+	{
649
+		return $this->status_ID() == EEM_Registration::status_id_approved ? true : false;
650
+	}
651
+
652
+
653
+	/**
654
+	 *    is_cancelled -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_cancelled
655
+	 *
656
+	 * @return        boolean
657
+	 */
658
+	public function is_cancelled()
659
+	{
660
+		return $this->status_ID() == EEM_Registration::status_id_cancelled ? true : false;
661
+	}
662
+
663
+
664
+	/**
665
+	 *    is_declined -  convenience method that returns TRUE if REG status ID == EEM_Registration::status_id_declined
666
+	 *
667
+	 * @return        boolean
668
+	 */
669
+	public function is_declined()
670
+	{
671
+		return $this->status_ID() == EEM_Registration::status_id_declined ? true : false;
672
+	}
673
+
674
+
675
+	/**
676
+	 *    is_incomplete -  convenience method that returns TRUE if REG status ID ==
677
+	 *    EEM_Registration::status_id_incomplete
678
+	 *
679
+	 * @return        boolean
680
+	 */
681
+	public function is_incomplete()
682
+	{
683
+		return $this->status_ID() == EEM_Registration::status_id_incomplete ? true : false;
684
+	}
685
+
686
+
687
+	/**
688
+	 *        Set Registration Date
689
+	 *
690
+	 * @param        mixed ( int or string ) $REG_date Registration Date - Unix timestamp or string representation of
691
+	 *                                                 Date
692
+	 * @throws EE_Error
693
+	 * @throws RuntimeException
694
+	 */
695
+	public function set_reg_date($REG_date = false)
696
+	{
697
+		$this->set('REG_date', $REG_date);
698
+	}
699
+
700
+
701
+	/**
702
+	 *    Set final price owing for this registration after all ticket/price modifications
703
+	 *
704
+	 * @access    public
705
+	 * @param    float $REG_final_price
706
+	 * @throws EE_Error
707
+	 * @throws RuntimeException
708
+	 */
709
+	public function set_final_price($REG_final_price = 0.00)
710
+	{
711
+		$this->set('REG_final_price', $REG_final_price);
712
+	}
713
+
714
+
715
+	/**
716
+	 *    Set amount paid towards this registration's final price
717
+	 *
718
+	 * @access    public
719
+	 * @param    float $REG_paid
720
+	 * @throws EE_Error
721
+	 * @throws RuntimeException
722
+	 */
723
+	public function set_paid($REG_paid = 0.00)
724
+	{
725
+		$this->set('REG_paid', $REG_paid);
726
+	}
727
+
728
+
729
+	/**
730
+	 *        Attendee Is Going
731
+	 *
732
+	 * @param        boolean $REG_att_is_going Attendee Is Going
733
+	 * @throws EE_Error
734
+	 * @throws RuntimeException
735
+	 */
736
+	public function set_att_is_going($REG_att_is_going = false)
737
+	{
738
+		$this->set('REG_att_is_going', $REG_att_is_going);
739
+	}
740
+
741
+
742
+	/**
743
+	 * Gets the related attendee
744
+	 *
745
+	 * @return EE_Attendee
746
+	 * @throws EE_Error
747
+	 */
748
+	public function attendee()
749
+	{
750
+		return $this->get_first_related('Attendee');
751
+	}
752
+
753
+
754
+	/**
755
+	 *        get Event ID
756
+	 */
757
+	public function event_ID()
758
+	{
759
+		return $this->get('EVT_ID');
760
+	}
761
+
762
+
763
+	/**
764
+	 *        get Event ID
765
+	 */
766
+	public function event_name()
767
+	{
768
+		$event = $this->event_obj();
769
+		if ($event) {
770
+			return $event->name();
771
+		} else {
772
+			return null;
773
+		}
774
+	}
775
+
776
+
777
+	/**
778
+	 * Fetches the event this registration is for
779
+	 *
780
+	 * @return EE_Event
781
+	 * @throws EE_Error
782
+	 */
783
+	public function event_obj()
784
+	{
785
+		return $this->get_first_related('Event');
786
+	}
787
+
788
+
789
+	/**
790
+	 *        get Attendee ID
791
+	 */
792
+	public function attendee_ID()
793
+	{
794
+		return $this->get('ATT_ID');
795
+	}
796
+
797
+
798
+	/**
799
+	 *        get PHP Session ID
800
+	 */
801
+	public function session_ID()
802
+	{
803
+		return $this->get('REG_session');
804
+	}
805
+
806
+
807
+	/**
808
+	 * Gets the string which represents the URL trigger for the receipt template in the message template system.
809
+	 *
810
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
811
+	 * @return string
812
+	 */
813
+	public function receipt_url($messenger = 'html')
814
+	{
815
+
816
+		/**
817
+		 * The below will be deprecated one version after this.  We check first if there is a custom receipt template
818
+		 * already in use on old system.  If there is then we just return the standard url for it.
819
+		 *
820
+		 * @since 4.5.0
821
+		 */
822
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/receipt_body.template.php';
823
+		$has_custom = EEH_Template::locate_template(
824
+			$template_relative_path,
825
+			array(),
826
+			true,
827
+			true,
828
+			true
829
+		);
830
+
831
+		if ($has_custom) {
832
+			return add_query_arg(array('receipt' => 'true'), $this->invoice_url('launch'));
833
+		}
834
+		return apply_filters('FHEE__EE_Registration__receipt_url__receipt_url', '', $this, $messenger, 'receipt');
835
+	}
836
+
837
+
838
+	/**
839
+	 * Gets the string which represents the URL trigger for the invoice template in the message template system.
840
+	 *
841
+	 * @param string $messenger 'pdf' or 'html'.  Default 'html'.
842
+	 * @return string
843
+	 * @throws EE_Error
844
+	 */
845
+	public function invoice_url($messenger = 'html')
846
+	{
847
+		/**
848
+		 * The below will be deprecated one version after this.  We check first if there is a custom invoice template
849
+		 * already in use on old system.  If there is then we just return the standard url for it.
850
+		 *
851
+		 * @since 4.5.0
852
+		 */
853
+		$template_relative_path = 'modules/gateways/Invoice/lib/templates/invoice_body.template.php';
854
+		$has_custom = EEH_Template::locate_template(
855
+			$template_relative_path,
856
+			array(),
857
+			true,
858
+			true,
859
+			true
860
+		);
861
+
862
+		if ($has_custom) {
863
+			if ($messenger == 'html') {
864
+				return $this->invoice_url('launch');
865
+			}
866
+			$route = $messenger == 'download' || $messenger == 'pdf' ? 'download_invoice' : 'launch_invoice';
867
+
868
+			$query_args = array('ee' => $route, 'id' => $this->reg_url_link());
869
+			if ($messenger == 'html') {
870
+				$query_args['html'] = true;
871
+			}
872
+			return add_query_arg($query_args, get_permalink(EE_Registry::instance()->CFG->core->thank_you_page_id));
873
+		}
874
+		return apply_filters('FHEE__EE_Registration__invoice_url__invoice_url', '', $this, $messenger, 'invoice');
875
+	}
876
+
877
+
878
+	/**
879
+	 * get Registration URL Link
880
+	 *
881
+	 * @access public
882
+	 * @return string
883
+	 * @throws EE_Error
884
+	 */
885
+	public function reg_url_link()
886
+	{
887
+		return (string) $this->get('REG_url_link');
888
+	}
889
+
890
+
891
+	/**
892
+	 * Echoes out invoice_url()
893
+	 *
894
+	 * @param string $type 'download','launch', or 'html' (default is 'launch')
895
+	 * @return void
896
+	 * @throws EE_Error
897
+	 */
898
+	public function e_invoice_url($type = 'launch')
899
+	{
900
+		echo $this->invoice_url($type);
901
+	}
902
+
903
+
904
+	/**
905
+	 * Echoes out payment_overview_url
906
+	 */
907
+	public function e_payment_overview_url()
908
+	{
909
+		echo $this->payment_overview_url();
910
+	}
911
+
912
+
913
+	/**
914
+	 * Gets the URL for the checkout payment options reg step
915
+	 * with this registration's REG_url_link added as a query parameter
916
+	 *
917
+	 * @param bool $clear_session Set to true when you want to clear the session on revisiting the
918
+	 *                            payment overview url.
919
+	 * @return string
920
+	 * @throws InvalidInterfaceException
921
+	 * @throws InvalidDataTypeException
922
+	 * @throws EE_Error
923
+	 * @throws InvalidArgumentException
924
+	 */
925
+	public function payment_overview_url($clear_session = false)
926
+	{
927
+		return add_query_arg(
928
+			(array) apply_filters(
929
+				'FHEE__EE_Registration__payment_overview_url__query_args',
930
+				array(
931
+					'e_reg_url_link' => $this->reg_url_link(),
932
+					'step'           => 'payment_options',
933
+					'revisit'        => true,
934
+					'clear_session'  => (bool) $clear_session,
935
+				),
936
+				$this
937
+			),
938
+			EE_Registry::instance()->CFG->core->reg_page_url()
939
+		);
940
+	}
941
+
942
+
943
+	/**
944
+	 * Gets the URL for the checkout attendee information reg step
945
+	 * with this registration's REG_url_link added as a query parameter
946
+	 *
947
+	 * @return string
948
+	 * @throws InvalidInterfaceException
949
+	 * @throws InvalidDataTypeException
950
+	 * @throws EE_Error
951
+	 * @throws InvalidArgumentException
952
+	 */
953
+	public function edit_attendee_information_url()
954
+	{
955
+		return add_query_arg(
956
+			(array) apply_filters(
957
+				'FHEE__EE_Registration__edit_attendee_information_url__query_args',
958
+				array(
959
+					'e_reg_url_link' => $this->reg_url_link(),
960
+					'step'           => 'attendee_information',
961
+					'revisit'        => true,
962
+				),
963
+				$this
964
+			),
965
+			EE_Registry::instance()->CFG->core->reg_page_url()
966
+		);
967
+	}
968
+
969
+
970
+	/**
971
+	 * Simply generates and returns the appropriate admin_url link to edit this registration
972
+	 *
973
+	 * @return string
974
+	 * @throws EE_Error
975
+	 */
976
+	public function get_admin_edit_url()
977
+	{
978
+		return EEH_URL::add_query_args_and_nonce(
979
+			array(
980
+				'page'    => 'espresso_registrations',
981
+				'action'  => 'view_registration',
982
+				'_REG_ID' => $this->ID(),
983
+			),
984
+			admin_url('admin.php')
985
+		);
986
+	}
987
+
988
+
989
+	/**
990
+	 *    is_primary_registrant?
991
+	 */
992
+	public function is_primary_registrant()
993
+	{
994
+		return $this->get('REG_count') === 1 ? true : false;
995
+	}
996
+
997
+
998
+	/**
999
+	 * This returns the primary registration object for this registration group (which may be this object).
1000
+	 *
1001
+	 * @return EE_Registration
1002
+	 * @throws EE_Error
1003
+	 */
1004
+	public function get_primary_registration()
1005
+	{
1006
+		if ($this->is_primary_registrant()) {
1007
+			return $this;
1008
+		}
1009
+
1010
+		// k reg_count !== 1 so let's get the EE_Registration object matching this txn_id and reg_count == 1
1011
+		/** @var EE_Registration $primary_registrant */
1012
+		$primary_registrant = EEM_Registration::instance()->get_one(
1013
+			array(
1014
+				array(
1015
+					'TXN_ID'    => $this->transaction_ID(),
1016
+					'REG_count' => 1,
1017
+				),
1018
+			)
1019
+		);
1020
+		return $primary_registrant;
1021
+	}
1022
+
1023
+
1024
+	/**
1025
+	 *        get  Attendee Number
1026
+	 *
1027
+	 * @access        public
1028
+	 */
1029
+	public function count()
1030
+	{
1031
+		return $this->get('REG_count');
1032
+	}
1033
+
1034
+
1035
+	/**
1036
+	 *        get Group Size
1037
+	 */
1038
+	public function group_size()
1039
+	{
1040
+		return $this->get('REG_group_size');
1041
+	}
1042
+
1043
+
1044
+	/**
1045
+	 *        get Registration Date
1046
+	 */
1047
+	public function date()
1048
+	{
1049
+		return $this->get('REG_date');
1050
+	}
1051
+
1052
+
1053
+	/**
1054
+	 * gets a pretty date
1055
+	 *
1056
+	 * @param string $date_format
1057
+	 * @param string $time_format
1058
+	 * @return string
1059
+	 * @throws EE_Error
1060
+	 */
1061
+	public function pretty_date($date_format = null, $time_format = null)
1062
+	{
1063
+		return $this->get_datetime('REG_date', $date_format, $time_format);
1064
+	}
1065
+
1066
+
1067
+	/**
1068
+	 * final_price
1069
+	 * the registration's share of the transaction total, so that the
1070
+	 * sum of all the transaction's REG_final_prices equal the transaction's total
1071
+	 *
1072
+	 * @return float
1073
+	 * @throws EE_Error
1074
+	 */
1075
+	public function final_price()
1076
+	{
1077
+		return $this->get('REG_final_price');
1078
+	}
1079
+
1080
+
1081
+	/**
1082
+	 * pretty_final_price
1083
+	 *  final price as formatted string, with correct decimal places and currency symbol
1084
+	 *
1085
+	 * @return string
1086
+	 * @throws EE_Error
1087
+	 */
1088
+	public function pretty_final_price()
1089
+	{
1090
+		return $this->get_pretty('REG_final_price');
1091
+	}
1092
+
1093
+
1094
+	/**
1095
+	 * get paid (yeah)
1096
+	 *
1097
+	 * @return float
1098
+	 * @throws EE_Error
1099
+	 */
1100
+	public function paid()
1101
+	{
1102
+		return $this->get('REG_paid');
1103
+	}
1104
+
1105
+
1106
+	/**
1107
+	 * pretty_paid
1108
+	 *
1109
+	 * @return float
1110
+	 * @throws EE_Error
1111
+	 */
1112
+	public function pretty_paid()
1113
+	{
1114
+		return $this->get_pretty('REG_paid');
1115
+	}
1116
+
1117
+
1118
+	/**
1119
+	 * owes_monies_and_can_pay
1120
+	 * whether or not this registration has monies owing and it's' status allows payment
1121
+	 *
1122
+	 * @param array $requires_payment
1123
+	 * @return bool
1124
+	 * @throws EE_Error
1125
+	 */
1126
+	public function owes_monies_and_can_pay($requires_payment = array())
1127
+	{
1128
+		// these reg statuses require payment (if event is not free)
1129
+		$requires_payment = ! empty($requires_payment)
1130
+			? $requires_payment
1131
+			: EEM_Registration::reg_statuses_that_allow_payment();
1132
+		if (in_array($this->status_ID(), $requires_payment) &&
1133
+			$this->final_price() != 0 &&
1134
+			$this->final_price() != $this->paid()
1135
+		) {
1136
+			return true;
1137
+		} else {
1138
+			return false;
1139
+		}
1140
+	}
1141
+
1142
+
1143
+	/**
1144
+	 * Prints out the return value of $this->pretty_status()
1145
+	 *
1146
+	 * @param bool $show_icons
1147
+	 * @return void
1148
+	 * @throws EE_Error
1149
+	 */
1150
+	public function e_pretty_status($show_icons = false)
1151
+	{
1152
+		echo $this->pretty_status($show_icons);
1153
+	}
1154
+
1155
+
1156
+	/**
1157
+	 * Returns a nice version of the status for displaying to customers
1158
+	 *
1159
+	 * @param bool $show_icons
1160
+	 * @return string
1161
+	 * @throws EE_Error
1162
+	 */
1163
+	public function pretty_status($show_icons = false)
1164
+	{
1165
+		$status = EEM_Status::instance()->localized_status(
1166
+			array($this->status_ID() => esc_html__('unknown', 'event_espresso')),
1167
+			false,
1168
+			'sentence'
1169
+		);
1170
+		$icon = '';
1171
+		switch ($this->status_ID()) {
1172
+			case EEM_Registration::status_id_approved:
1173
+				$icon = $show_icons
1174
+					? '<span class="dashicons dashicons-star-filled ee-icon-size-16 green-text"></span>'
1175
+					: '';
1176
+				break;
1177
+			case EEM_Registration::status_id_pending_payment:
1178
+				$icon = $show_icons
1179
+					? '<span class="dashicons dashicons-star-half ee-icon-size-16 orange-text"></span>'
1180
+					: '';
1181
+				break;
1182
+			case EEM_Registration::status_id_not_approved:
1183
+				$icon = $show_icons
1184
+					? '<span class="dashicons dashicons-marker ee-icon-size-16 orange-text"></span>'
1185
+					: '';
1186
+				break;
1187
+			case EEM_Registration::status_id_cancelled:
1188
+				$icon = $show_icons
1189
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-grey-text"></span>'
1190
+					: '';
1191
+				break;
1192
+			case EEM_Registration::status_id_incomplete:
1193
+				$icon = $show_icons
1194
+					? '<span class="dashicons dashicons-no ee-icon-size-16 lt-orange-text"></span>'
1195
+					: '';
1196
+				break;
1197
+			case EEM_Registration::status_id_declined:
1198
+				$icon = $show_icons
1199
+					? '<span class="dashicons dashicons-no ee-icon-size-16 red-text"></span>'
1200
+					: '';
1201
+				break;
1202
+			case EEM_Registration::status_id_wait_list:
1203
+				$icon = $show_icons
1204
+					? '<span class="dashicons dashicons-clipboard ee-icon-size-16 purple-text"></span>'
1205
+					: '';
1206
+				break;
1207
+		}
1208
+		return $icon . $status[ $this->status_ID() ];
1209
+	}
1210
+
1211
+
1212
+	/**
1213
+	 *        get Attendee Is Going
1214
+	 */
1215
+	public function att_is_going()
1216
+	{
1217
+		return $this->get('REG_att_is_going');
1218
+	}
1219
+
1220
+
1221
+	/**
1222
+	 * Gets related answers
1223
+	 *
1224
+	 * @param array $query_params @see https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md
1225
+	 * @return EE_Answer[]
1226
+	 * @throws EE_Error
1227
+	 */
1228
+	public function answers($query_params = null)
1229
+	{
1230
+		return $this->get_many_related('Answer', $query_params);
1231
+	}
1232
+
1233
+
1234
+	/**
1235
+	 * Gets the registration's answer value to the specified question
1236
+	 * (either the question's ID or a question object)
1237
+	 *
1238
+	 * @param EE_Question|int $question
1239
+	 * @param bool            $pretty_value
1240
+	 * @return array|string if pretty_value= true, the result will always be a string
1241
+	 * (because the answer might be an array of answer values, so passing pretty_value=true
1242
+	 * will convert it into some kind of string)
1243
+	 * @throws EE_Error
1244
+	 */
1245
+	public function answer_value_to_question($question, $pretty_value = true)
1246
+	{
1247
+		$question_id = EEM_Question::instance()->ensure_is_ID($question);
1248
+		return EEM_Answer::instance()->get_answer_value_to_question($this, $question_id, $pretty_value);
1249
+	}
1250
+
1251
+
1252
+	/**
1253
+	 * question_groups
1254
+	 * returns an array of EE_Question_Group objects for this registration
1255
+	 *
1256
+	 * @return EE_Question_Group[]
1257
+	 * @throws EE_Error
1258
+	 * @throws InvalidArgumentException
1259
+	 * @throws InvalidDataTypeException
1260
+	 * @throws InvalidInterfaceException
1261
+	 * @throws ReflectionException
1262
+	 */
1263
+	public function question_groups()
1264
+	{
1265
+		return EEM_Event::instance()->get_question_groups_for_event($this->event_ID(), $this);
1266
+	}
1267
+
1268
+
1269
+	/**
1270
+	 * count_question_groups
1271
+	 * returns a count of the number of EE_Question_Group objects for this registration
1272
+	 *
1273
+	 * @return int
1274
+	 * @throws EE_Error
1275
+	 * @throws EntityNotFoundException
1276
+	 * @throws InvalidArgumentException
1277
+	 * @throws InvalidDataTypeException
1278
+	 * @throws InvalidInterfaceException
1279
+	 * @throws ReflectionException
1280
+	 */
1281
+	public function count_question_groups()
1282
+	{
1283
+		return EEM_Event::instance()->count_related(
1284
+			$this->event_ID(),
1285
+			'Question_Group',
1286
+			[
1287
+				[
1288
+					'Event_Question_Group.'
1289
+					. EEM_Event_Question_Group::instance()->fieldNameForContext($this->is_primary_registrant()) => true,
1290
+				]
1291
+			]
1292
+		);
1293
+	}
1294
+
1295
+
1296
+	/**
1297
+	 * Returns the registration date in the 'standard' string format
1298
+	 * (function may be improved in the future to allow for different formats and timezones)
1299
+	 *
1300
+	 * @return string
1301
+	 * @throws EE_Error
1302
+	 */
1303
+	public function reg_date()
1304
+	{
1305
+		return $this->get_datetime('REG_date');
1306
+	}
1307
+
1308
+
1309
+	/**
1310
+	 * Gets the datetime-ticket for this registration (ie, it can be used to isolate
1311
+	 * the ticket this registration purchased, or the datetime they have registered
1312
+	 * to attend)
1313
+	 *
1314
+	 * @return EE_Datetime_Ticket
1315
+	 * @throws EE_Error
1316
+	 */
1317
+	public function datetime_ticket()
1318
+	{
1319
+		return $this->get_first_related('Datetime_Ticket');
1320
+	}
1321
+
1322
+
1323
+	/**
1324
+	 * Sets the registration's datetime_ticket.
1325
+	 *
1326
+	 * @param EE_Datetime_Ticket $datetime_ticket
1327
+	 * @return EE_Datetime_Ticket
1328
+	 * @throws EE_Error
1329
+	 */
1330
+	public function set_datetime_ticket($datetime_ticket)
1331
+	{
1332
+		return $this->_add_relation_to($datetime_ticket, 'Datetime_Ticket');
1333
+	}
1334
+
1335
+	/**
1336
+	 * Gets deleted
1337
+	 *
1338
+	 * @return bool
1339
+	 * @throws EE_Error
1340
+	 */
1341
+	public function deleted()
1342
+	{
1343
+		return $this->get('REG_deleted');
1344
+	}
1345
+
1346
+	/**
1347
+	 * Sets deleted
1348
+	 *
1349
+	 * @param boolean $deleted
1350
+	 * @return bool
1351
+	 * @throws EE_Error
1352
+	 * @throws RuntimeException
1353
+	 */
1354
+	public function set_deleted($deleted)
1355
+	{
1356
+		if ($deleted) {
1357
+			$this->delete();
1358
+		} else {
1359
+			$this->restore();
1360
+		}
1361
+	}
1362
+
1363
+
1364
+	/**
1365
+	 * Get the status object of this object
1366
+	 *
1367
+	 * @return EE_Status
1368
+	 * @throws EE_Error
1369
+	 */
1370
+	public function status_obj()
1371
+	{
1372
+		return $this->get_first_related('Status');
1373
+	}
1374
+
1375
+
1376
+	/**
1377
+	 * Returns the number of times this registration has checked into any of the datetimes
1378
+	 * its available for
1379
+	 *
1380
+	 * @return int
1381
+	 * @throws EE_Error
1382
+	 */
1383
+	public function count_checkins()
1384
+	{
1385
+		return $this->get_model()->count_related($this, 'Checkin');
1386
+	}
1387
+
1388
+
1389
+	/**
1390
+	 * Returns the number of current Check-ins this registration is checked into for any of the datetimes the
1391
+	 * registration is for.  Note, this is ONLY checked in (does not include checkedout)
1392
+	 *
1393
+	 * @return int
1394
+	 * @throws EE_Error
1395
+	 */
1396
+	public function count_checkins_not_checkedout()
1397
+	{
1398
+		return $this->get_model()->count_related($this, 'Checkin', array(array('CHK_in' => 1)));
1399
+	}
1400
+
1401
+
1402
+	/**
1403
+	 * The purpose of this method is simply to check whether this registration can checkin to the given datetime.
1404
+	 *
1405
+	 * @param int | EE_Datetime $DTT_OR_ID      The datetime the registration is being checked against
1406
+	 * @param bool              $check_approved This is used to indicate whether the caller wants can_checkin to also
1407
+	 *                                          consider registration status as well as datetime access.
1408
+	 * @return bool
1409
+	 * @throws EE_Error
1410
+	 */
1411
+	public function can_checkin($DTT_OR_ID, $check_approved = true)
1412
+	{
1413
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1414
+
1415
+		// first check registration status
1416
+		if (($check_approved && ! $this->is_approved()) || ! $DTT_ID) {
1417
+			return false;
1418
+		}
1419
+		// is there a datetime ticket that matches this dtt_ID?
1420
+		if (! (EEM_Datetime_Ticket::instance()->exists(
1421
+			array(
1422
+				array(
1423
+					'TKT_ID' => $this->get('TKT_ID'),
1424
+					'DTT_ID' => $DTT_ID,
1425
+				),
1426
+			)
1427
+		))
1428
+		) {
1429
+			return false;
1430
+		}
1431
+
1432
+		// final check is against TKT_uses
1433
+		return $this->verify_can_checkin_against_TKT_uses($DTT_ID);
1434
+	}
1435
+
1436
+
1437
+	/**
1438
+	 * This method verifies whether the user can checkin for the given datetime considering the max uses value set on
1439
+	 * the ticket. To do this,  a query is done to get the count of the datetime records already checked into.  If the
1440
+	 * datetime given does not have a check-in record and checking in for that datetime will exceed the allowed uses,
1441
+	 * then return false.  Otherwise return true.
1442
+	 *
1443
+	 * @param int | EE_Datetime $DTT_OR_ID The datetime the registration is being checked against
1444
+	 * @return bool true means can checkin.  false means cannot checkin.
1445
+	 * @throws EE_Error
1446
+	 */
1447
+	public function verify_can_checkin_against_TKT_uses($DTT_OR_ID)
1448
+	{
1449
+		$DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1450
+
1451
+		if (! $DTT_ID) {
1452
+			return false;
1453
+		}
1454
+
1455
+		$max_uses = $this->ticket() instanceof EE_Ticket ? $this->ticket()->uses() : EE_INF;
1456
+
1457
+		// if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1458
+		// check-in or not.
1459
+		if (! $max_uses || $max_uses === EE_INF) {
1460
+			return true;
1461
+		}
1462
+
1463
+		// does this datetime have a checkin record?  If so, then the dtt count has already been verified so we can just
1464
+		// go ahead and toggle.
1465
+		if (EEM_Checkin::instance()->exists(array(array('REG_ID' => $this->ID(), 'DTT_ID' => $DTT_ID)))) {
1466
+			return true;
1467
+		}
1468
+
1469
+		// made it here so the last check is whether the number of checkins per unique datetime on this registration
1470
+		// disallows further check-ins.
1471
+		$count_unique_dtt_checkins = EEM_Checkin::instance()->count(
1472
+			array(
1473
+				array(
1474
+					'REG_ID' => $this->ID(),
1475
+					'CHK_in' => true,
1476
+				),
1477
+			),
1478
+			'DTT_ID',
1479
+			true
1480
+		);
1481
+		// checkins have already reached their max number of uses
1482
+		// so registrant can NOT checkin
1483
+		if ($count_unique_dtt_checkins >= $max_uses) {
1484
+			EE_Error::add_error(
1485
+				esc_html__(
1486
+					'Check-in denied because number of datetime uses for the ticket has been reached or exceeded.',
1487
+					'event_espresso'
1488
+				),
1489
+				__FILE__,
1490
+				__FUNCTION__,
1491
+				__LINE__
1492
+			);
1493
+			return false;
1494
+		}
1495
+		return true;
1496
+	}
1497
+
1498
+
1499
+	/**
1500
+	 * toggle Check-in status for this registration
1501
+	 * Check-ins are toggled in the following order:
1502
+	 * never checked in -> checked in
1503
+	 * checked in -> checked out
1504
+	 * checked out -> checked in
1505
+	 *
1506
+	 * @param  int $DTT_ID  include specific datetime to toggle Check-in for.
1507
+	 *                      If not included or null, then it is assumed latest datetime is being toggled.
1508
+	 * @param bool $verify  If true then can_checkin() is used to verify whether the person
1509
+	 *                      can be checked in or not.  Otherwise this forces change in checkin status.
1510
+	 * @return bool|int     the chk_in status toggled to OR false if nothing got changed.
1511
+	 * @throws EE_Error
1512
+	 */
1513
+	public function toggle_checkin_status($DTT_ID = null, $verify = false)
1514
+	{
1515
+		if (empty($DTT_ID)) {
1516
+			$datetime = $this->get_latest_related_datetime();
1517
+			$DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1518
+			// verify the registration can checkin for the given DTT_ID
1519
+		} elseif (! $this->can_checkin($DTT_ID, $verify)) {
1520
+			EE_Error::add_error(
1521
+				sprintf(
1522
+					esc_html__(
1523
+						'The given registration (ID:%1$d) can not be checked in to the given DTT_ID (%2$d), because the registration does not have access',
1524
+						'event_espresso'
1525
+					),
1526
+					$this->ID(),
1527
+					$DTT_ID
1528
+				),
1529
+				__FILE__,
1530
+				__FUNCTION__,
1531
+				__LINE__
1532
+			);
1533
+			return false;
1534
+		}
1535
+		$status_paths = array(
1536
+			EE_Checkin::status_checked_never => EE_Checkin::status_checked_in,
1537
+			EE_Checkin::status_checked_in    => EE_Checkin::status_checked_out,
1538
+			EE_Checkin::status_checked_out   => EE_Checkin::status_checked_in,
1539
+		);
1540
+		// start by getting the current status so we know what status we'll be changing to.
1541
+		$cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1542
+		$status_to = $status_paths[ $cur_status ];
1543
+		// database only records true for checked IN or false for checked OUT
1544
+		// no record ( null ) means checked in NEVER, but we obviously don't save that
1545
+		$new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
1546
+		// add relation - note Check-ins are always creating new rows
1547
+		// because we are keeping track of Check-ins over time.
1548
+		// Eventually we'll probably want to show a list table
1549
+		// for the individual Check-ins so that they can be managed.
1550
+		$checkin = EE_Checkin::new_instance(
1551
+			array(
1552
+				'REG_ID' => $this->ID(),
1553
+				'DTT_ID' => $DTT_ID,
1554
+				'CHK_in' => $new_status,
1555
+			)
1556
+		);
1557
+		// if the record could not be saved then return false
1558
+		if ($checkin->save() === 0) {
1559
+			if (WP_DEBUG) {
1560
+				global $wpdb;
1561
+				$error = sprintf(
1562
+					esc_html__(
1563
+						'Registration check in update failed because of the following database error: %1$s%2$s',
1564
+						'event_espresso'
1565
+					),
1566
+					'<br />',
1567
+					$wpdb->last_error
1568
+				);
1569
+			} else {
1570
+				$error = esc_html__(
1571
+					'Registration check in update failed because of an unknown database error',
1572
+					'event_espresso'
1573
+				);
1574
+			}
1575
+			EE_Error::add_error($error, __FILE__, __FUNCTION__, __LINE__);
1576
+			return false;
1577
+		}
1578
+		return $status_to;
1579
+	}
1580
+
1581
+
1582
+	/**
1583
+	 * Returns the latest datetime related to this registration (via the ticket attached to the registration).
1584
+	 * "Latest" is defined by the `DTT_EVT_start` column.
1585
+	 *
1586
+	 * @return EE_Datetime|null
1587
+	 * @throws EE_Error
1588
+	 */
1589
+	public function get_latest_related_datetime()
1590
+	{
1591
+		return EEM_Datetime::instance()->get_one(
1592
+			array(
1593
+				array(
1594
+					'Ticket.Registration.REG_ID' => $this->ID(),
1595
+				),
1596
+				'order_by' => array('DTT_EVT_start' => 'DESC'),
1597
+			)
1598
+		);
1599
+	}
1600
+
1601
+
1602
+	/**
1603
+	 * Returns the earliest datetime related to this registration (via the ticket attached to the registration).
1604
+	 * "Earliest" is defined by the `DTT_EVT_start` column.
1605
+	 *
1606
+	 * @throws EE_Error
1607
+	 */
1608
+	public function get_earliest_related_datetime()
1609
+	{
1610
+		return EEM_Datetime::instance()->get_one(
1611
+			array(
1612
+				array(
1613
+					'Ticket.Registration.REG_ID' => $this->ID(),
1614
+				),
1615
+				'order_by' => array('DTT_EVT_start' => 'ASC'),
1616
+			)
1617
+		);
1618
+	}
1619
+
1620
+
1621
+	/**
1622
+	 * This method simply returns the check-in status for this registration and the given datetime.
1623
+	 * If neither the datetime nor the checkin values are provided as arguments,
1624
+	 * then this will return the LATEST check-in status for the registration across all datetimes it belongs to.
1625
+	 *
1626
+	 * @param  int       $DTT_ID  The ID of the datetime we're checking against
1627
+	 *                            (if empty we'll get the primary datetime for
1628
+	 *                            this registration (via event) and use it's ID);
1629
+	 * @param EE_Checkin $checkin If present, we use the given checkin object rather than the dtt_id.
1630
+	 *
1631
+	 * @return int                Integer representing Check-in status.
1632
+	 * @throws EE_Error
1633
+	 */
1634
+	public function check_in_status_for_datetime($DTT_ID = 0, $checkin = null)
1635
+	{
1636
+		$checkin_query_params = array(
1637
+			'order_by' => array('CHK_timestamp' => 'DESC'),
1638
+		);
1639
+
1640
+		if ($DTT_ID > 0) {
1641
+			$checkin_query_params[0] = array('DTT_ID' => $DTT_ID);
1642
+		}
1643
+
1644
+		// get checkin object (if exists)
1645
+		$checkin = $checkin instanceof EE_Checkin
1646
+			? $checkin
1647
+			: $this->get_first_related('Checkin', $checkin_query_params);
1648
+		if ($checkin instanceof EE_Checkin) {
1649
+			if ($checkin->get('CHK_in')) {
1650
+				return EE_Checkin::status_checked_in; // checked in
1651
+			}
1652
+			return EE_Checkin::status_checked_out; // had checked in but is now checked out.
1653
+		}
1654
+		return EE_Checkin::status_checked_never; // never been checked in
1655
+	}
1656
+
1657
+
1658
+	/**
1659
+	 * This method returns a localized message for the toggled Check-in message.
1660
+	 *
1661
+	 * @param  int $DTT_ID include specific datetime to get the correct Check-in message.  If not included or null,
1662
+	 *                     then it is assumed Check-in for primary datetime was toggled.
1663
+	 * @param bool $error  This just flags that you want an error message returned. This is put in so that the error
1664
+	 *                     message can be customized with the attendee name.
1665
+	 * @return string internationalized message
1666
+	 * @throws EE_Error
1667
+	 */
1668
+	public function get_checkin_msg($DTT_ID, $error = false)
1669
+	{
1670
+		// let's get the attendee first so we can include the name of the attendee
1671
+		$attendee = $this->get_first_related('Attendee');
1672
+		if ($attendee instanceof EE_Attendee) {
1673
+			if ($error) {
1674
+				return sprintf(__("%s's check-in status was not changed.", "event_espresso"), $attendee->full_name());
1675
+			}
1676
+			$cur_status = $this->check_in_status_for_datetime($DTT_ID);
1677
+			// what is the status message going to be?
1678
+			switch ($cur_status) {
1679
+				case EE_Checkin::status_checked_never:
1680
+					return sprintf(
1681
+						__("%s has been removed from Check-in records", "event_espresso"),
1682
+						$attendee->full_name()
1683
+					);
1684
+					break;
1685
+				case EE_Checkin::status_checked_in:
1686
+					return sprintf(__('%s has been checked in', 'event_espresso'), $attendee->full_name());
1687
+					break;
1688
+				case EE_Checkin::status_checked_out:
1689
+					return sprintf(__('%s has been checked out', 'event_espresso'), $attendee->full_name());
1690
+					break;
1691
+			}
1692
+		}
1693
+		return esc_html__("The check-in status could not be determined.", "event_espresso");
1694
+	}
1695
+
1696
+
1697
+	/**
1698
+	 * Returns the related EE_Transaction to this registration
1699
+	 *
1700
+	 * @return EE_Transaction
1701
+	 * @throws EE_Error
1702
+	 * @throws EntityNotFoundException
1703
+	 */
1704
+	public function transaction()
1705
+	{
1706
+		$transaction = $this->get_first_related('Transaction');
1707
+		if (! $transaction instanceof \EE_Transaction) {
1708
+			throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1709
+		}
1710
+		return $transaction;
1711
+	}
1712
+
1713
+
1714
+	/**
1715
+	 *        get Registration Code
1716
+	 */
1717
+	public function reg_code()
1718
+	{
1719
+		return $this->get('REG_code');
1720
+	}
1721
+
1722
+
1723
+	/**
1724
+	 *        get Transaction ID
1725
+	 */
1726
+	public function transaction_ID()
1727
+	{
1728
+		return $this->get('TXN_ID');
1729
+	}
1730
+
1731
+
1732
+	/**
1733
+	 * @return int
1734
+	 * @throws EE_Error
1735
+	 */
1736
+	public function ticket_ID()
1737
+	{
1738
+		return $this->get('TKT_ID');
1739
+	}
1740
+
1741
+
1742
+	/**
1743
+	 *        Set Registration Code
1744
+	 *
1745
+	 * @access    public
1746
+	 * @param    string  $REG_code Registration Code
1747
+	 * @param    boolean $use_default
1748
+	 * @throws EE_Error
1749
+	 */
1750
+	public function set_reg_code($REG_code, $use_default = false)
1751
+	{
1752
+		if (empty($REG_code)) {
1753
+			EE_Error::add_error(
1754
+				esc_html__('REG_code can not be empty.', 'event_espresso'),
1755
+				__FILE__,
1756
+				__FUNCTION__,
1757
+				__LINE__
1758
+			);
1759
+			return;
1760
+		}
1761
+		if (! $this->reg_code()) {
1762
+			parent::set('REG_code', $REG_code, $use_default);
1763
+		} else {
1764
+			EE_Error::doing_it_wrong(
1765
+				__CLASS__ . '::' . __FUNCTION__,
1766
+				esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1767
+				'4.6.0'
1768
+			);
1769
+		}
1770
+	}
1771
+
1772
+
1773
+	/**
1774
+	 * Returns all other registrations in the same group as this registrant who have the same ticket option.
1775
+	 * Note, if you want to just get all registrations in the same transaction (group), use:
1776
+	 *    $registration->transaction()->registrations();
1777
+	 *
1778
+	 * @since 4.5.0
1779
+	 * @return EE_Registration[] or empty array if this isn't a group registration.
1780
+	 * @throws EE_Error
1781
+	 */
1782
+	public function get_all_other_registrations_in_group()
1783
+	{
1784
+		if ($this->group_size() < 2) {
1785
+			return array();
1786
+		}
1787
+
1788
+		$query[0] = array(
1789
+			'TXN_ID' => $this->transaction_ID(),
1790
+			'REG_ID' => array('!=', $this->ID()),
1791
+			'TKT_ID' => $this->ticket_ID(),
1792
+		);
1793
+		/** @var EE_Registration[] $registrations */
1794
+		$registrations = $this->get_model()->get_all($query);
1795
+		return $registrations;
1796
+	}
1797
+
1798
+	/**
1799
+	 * Return the link to the admin details for the object.
1800
+	 *
1801
+	 * @return string
1802
+	 * @throws EE_Error
1803
+	 */
1804
+	public function get_admin_details_link()
1805
+	{
1806
+		EE_Registry::instance()->load_helper('URL');
1807
+		return EEH_URL::add_query_args_and_nonce(
1808
+			array(
1809
+				'page'    => 'espresso_registrations',
1810
+				'action'  => 'view_registration',
1811
+				'_REG_ID' => $this->ID(),
1812
+			),
1813
+			admin_url('admin.php')
1814
+		);
1815
+	}
1816
+
1817
+	/**
1818
+	 * Returns the link to the editor for the object.  Sometimes this is the same as the details.
1819
+	 *
1820
+	 * @return string
1821
+	 * @throws EE_Error
1822
+	 */
1823
+	public function get_admin_edit_link()
1824
+	{
1825
+		return $this->get_admin_details_link();
1826
+	}
1827
+
1828
+	/**
1829
+	 * Returns the link to a settings page for the object.
1830
+	 *
1831
+	 * @return string
1832
+	 * @throws EE_Error
1833
+	 */
1834
+	public function get_admin_settings_link()
1835
+	{
1836
+		return $this->get_admin_details_link();
1837
+	}
1838
+
1839
+	/**
1840
+	 * Returns the link to the "overview" for the object (typically the "list table" view).
1841
+	 *
1842
+	 * @return string
1843
+	 */
1844
+	public function get_admin_overview_link()
1845
+	{
1846
+		EE_Registry::instance()->load_helper('URL');
1847
+		return EEH_URL::add_query_args_and_nonce(
1848
+			array(
1849
+				'page' => 'espresso_registrations',
1850
+			),
1851
+			admin_url('admin.php')
1852
+		);
1853
+	}
1854
+
1855
+
1856
+	/**
1857
+	 * @param array $query_params
1858
+	 *
1859
+	 * @return \EE_Registration[]
1860
+	 * @throws EE_Error
1861
+	 */
1862
+	public function payments($query_params = array())
1863
+	{
1864
+		return $this->get_many_related('Payment', $query_params);
1865
+	}
1866
+
1867
+
1868
+	/**
1869
+	 * @param array $query_params
1870
+	 *
1871
+	 * @return \EE_Registration_Payment[]
1872
+	 * @throws EE_Error
1873
+	 */
1874
+	public function registration_payments($query_params = array())
1875
+	{
1876
+		return $this->get_many_related('Registration_Payment', $query_params);
1877
+	}
1878
+
1879
+
1880
+	/**
1881
+	 * This grabs the payment method corresponding to the last payment made for the amount owing on the registration.
1882
+	 * Note: if there are no payments on the registration there will be no payment method returned.
1883
+	 *
1884
+	 * @return EE_Payment_Method|null
1885
+	 */
1886
+	public function payment_method()
1887
+	{
1888
+		return EEM_Payment_Method::instance()->get_last_used_for_registration($this);
1889
+	}
1890
+
1891
+
1892
+	/**
1893
+	 * @return \EE_Line_Item
1894
+	 * @throws EntityNotFoundException
1895
+	 * @throws EE_Error
1896
+	 */
1897
+	public function ticket_line_item()
1898
+	{
1899
+		$ticket = $this->ticket();
1900
+		$transaction = $this->transaction();
1901
+		$line_item = null;
1902
+		$ticket_line_items = \EEH_Line_Item::get_line_items_by_object_type_and_IDs(
1903
+			$transaction->total_line_item(),
1904
+			'Ticket',
1905
+			array($ticket->ID())
1906
+		);
1907
+		foreach ($ticket_line_items as $ticket_line_item) {
1908
+			if ($ticket_line_item instanceof \EE_Line_Item
1909
+				&& $ticket_line_item->OBJ_type() === 'Ticket'
1910
+				&& $ticket_line_item->OBJ_ID() === $ticket->ID()
1911
+			) {
1912
+				$line_item = $ticket_line_item;
1913
+				break;
1914
+			}
1915
+		}
1916
+		if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1917
+			throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1918
+		}
1919
+		return $line_item;
1920
+	}
1921
+
1922
+
1923
+	/**
1924
+	 * Soft Deletes this model object.
1925
+	 *
1926
+	 * @return boolean | int
1927
+	 * @throws RuntimeException
1928
+	 * @throws EE_Error
1929
+	 */
1930
+	public function delete()
1931
+	{
1932
+		if ($this->update_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY, $this->status_ID()) === true) {
1933
+			$this->set_status(EEM_Registration::status_id_cancelled);
1934
+		}
1935
+		return parent::delete();
1936
+	}
1937
+
1938
+
1939
+	/**
1940
+	 * Restores whatever the previous status was on a registration before it was trashed (if possible)
1941
+	 *
1942
+	 * @throws EE_Error
1943
+	 * @throws RuntimeException
1944
+	 */
1945
+	public function restore()
1946
+	{
1947
+		$previous_status = $this->get_extra_meta(
1948
+			EE_Registration::PRE_TRASH_REG_STATUS_KEY,
1949
+			true,
1950
+			EEM_Registration::status_id_cancelled
1951
+		);
1952
+		if ($previous_status) {
1953
+			$this->delete_extra_meta(EE_Registration::PRE_TRASH_REG_STATUS_KEY);
1954
+			$this->set_status($previous_status);
1955
+		}
1956
+		return parent::restore();
1957
+	}
1958
+
1959
+
1960
+	/**
1961
+	 * possibly toggle Registration status based on comparison of REG_paid vs REG_final_price
1962
+	 *
1963
+	 * @param  boolean $trigger_set_status_logic EE_Registration::set_status() can trigger additional logic
1964
+	 *                                           depending on whether the reg status changes to or from "Approved"
1965
+	 * @return boolean whether the Registration status was updated
1966
+	 * @throws EE_Error
1967
+	 * @throws RuntimeException
1968
+	 */
1969
+	public function updateStatusBasedOnTotalPaid($trigger_set_status_logic = true)
1970
+	{
1971
+		$paid = $this->paid();
1972
+		$price = $this->final_price();
1973
+		switch (true) {
1974
+			// overpaid or paid
1975
+			case EEH_Money::compare_floats($paid, $price, '>'):
1976
+			case EEH_Money::compare_floats($paid, $price):
1977
+				$new_status = EEM_Registration::status_id_approved;
1978
+				break;
1979
+			//  underpaid
1980
+			case EEH_Money::compare_floats($paid, $price, '<'):
1981
+				$new_status = EEM_Registration::status_id_pending_payment;
1982
+				break;
1983
+			// uhhh Houston...
1984
+			default:
1985
+				throw new RuntimeException(
1986
+					esc_html__('The total paid calculation for this registration is inaccurate.', 'event_espresso')
1987
+				);
1988
+		}
1989
+		if ($new_status !== $this->status_ID()) {
1990
+			if ($trigger_set_status_logic) {
1991
+				return $this->set_status($new_status);
1992
+			}
1993
+			parent::set('STS_ID', $new_status);
1994
+			return true;
1995
+		}
1996
+		return false;
1997
+	}
1998
+
1999
+
2000
+	/*************************** DEPRECATED ***************************/
2001
+
2002
+
2003
+	/**
2004
+	 * @deprecated
2005
+	 * @since     4.7.0
2006
+	 * @access    public
2007
+	 */
2008
+	public function price_paid()
2009
+	{
2010
+		EE_Error::doing_it_wrong(
2011
+			'EE_Registration::price_paid()',
2012
+			esc_html__(
2013
+				'This method is deprecated, please use EE_Registration::final_price() instead.',
2014
+				'event_espresso'
2015
+			),
2016
+			'4.7.0'
2017
+		);
2018
+		return $this->final_price();
2019
+	}
2020
+
2021
+
2022
+	/**
2023
+	 * @deprecated
2024
+	 * @since     4.7.0
2025
+	 * @access    public
2026
+	 * @param    float $REG_final_price
2027
+	 * @throws EE_Error
2028
+	 * @throws RuntimeException
2029
+	 */
2030
+	public function set_price_paid($REG_final_price = 0.00)
2031
+	{
2032
+		EE_Error::doing_it_wrong(
2033
+			'EE_Registration::set_price_paid()',
2034
+			esc_html__(
2035
+				'This method is deprecated, please use EE_Registration::set_final_price() instead.',
2036
+				'event_espresso'
2037
+			),
2038
+			'4.7.0'
2039
+		);
2040
+		$this->set_final_price($REG_final_price);
2041
+	}
2042
+
2043
+
2044
+	/**
2045
+	 * @deprecated
2046
+	 * @since 4.7.0
2047
+	 * @return string
2048
+	 * @throws EE_Error
2049
+	 */
2050
+	public function pretty_price_paid()
2051
+	{
2052
+		EE_Error::doing_it_wrong(
2053
+			'EE_Registration::pretty_price_paid()',
2054
+			esc_html__(
2055
+				'This method is deprecated, please use EE_Registration::pretty_final_price() instead.',
2056
+				'event_espresso'
2057
+			),
2058
+			'4.7.0'
2059
+		);
2060
+		return $this->pretty_final_price();
2061
+	}
2062
+
2063
+
2064
+	/**
2065
+	 * Gets the primary datetime related to this registration via the related Event to this registration
2066
+	 *
2067
+	 * @deprecated 4.9.17
2068
+	 * @return EE_Datetime
2069
+	 * @throws EE_Error
2070
+	 * @throws EntityNotFoundException
2071
+	 */
2072
+	public function get_related_primary_datetime()
2073
+	{
2074
+		EE_Error::doing_it_wrong(
2075
+			__METHOD__,
2076
+			esc_html__(
2077
+				'Use EE_Registration::get_latest_related_datetime() or EE_Registration::get_earliest_related_datetime()',
2078
+				'event_espresso'
2079
+			),
2080
+			'4.9.17',
2081
+			'5.0.0'
2082
+		);
2083
+		return $this->event()->primary_datetime();
2084
+	}
2085
+
2086
+	public function name()
2087
+	{
2088
+		$attendee = $this->attendee();
2089
+		if($attendee instanceof EE_Attendee){
2090
+			$attendee_name = $attendee->full_name();
2091
+		} else {
2092
+			$attendee_name = esc_html__('Unknown', 'event_espresso');
2093
+		}
2094
+		return esc_html(
2095
+			sprintf(
2096
+				// translators: 1: registration code, 2: number, 3: group size, 4: attendee name.
2097
+				__('Registration with code "%1$s", %2$d of %3$d for %4$s', 'event_espresso'),
2098
+				$this->reg_code(),
2099
+				$this->count(),
2100
+				$this->group_size(),
2101
+				$attendee_name
2102
+			)
2103
+		);
2104
+	}
2105 2105
 }
Please login to merge, or discard this patch.
Spacing   +16 added lines, -16 removed lines patch added patch discarded remove patch
@@ -119,7 +119,7 @@  discard block
 block discarded – undo
119 119
     {
120 120
         switch ($field_name) {
121 121
             case 'REG_code':
122
-                if (! empty($field_value) && $this->reg_code() === null) {
122
+                if ( ! empty($field_value) && $this->reg_code() === null) {
123 123
                     $this->set_reg_code($field_value, $use_default);
124 124
                 }
125 125
                 break;
@@ -403,7 +403,7 @@  discard block
 block discarded – undo
403 403
     public function event()
404 404
     {
405 405
         $event = $this->get_first_related('Event');
406
-        if (! $event instanceof \EE_Event) {
406
+        if ( ! $event instanceof \EE_Event) {
407 407
             throw new EntityNotFoundException('Event ID', $this->event_ID());
408 408
         }
409 409
         return $event;
@@ -446,7 +446,7 @@  discard block
 block discarded – undo
446 446
     {
447 447
         // reserved ticket and datetime counts will be decremented as sold counts are incremented
448 448
         // so stop tracking that this reg has a ticket reserved
449
-        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
449
+        $this->release_reserved_ticket(false, "REG: {$this->ID()} (ln:".__LINE__.')');
450 450
         $ticket = $this->ticket();
451 451
         $ticket->increaseSold();
452 452
         // possibly set event status to sold out
@@ -500,7 +500,7 @@  discard block
 block discarded – undo
500 500
                 && $update_ticket
501 501
             ) {
502 502
                 $ticket = $this->ticket();
503
-                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
503
+                $ticket->increaseReserved(1, "REG: {$this->ID()} (ln:".__LINE__.')');
504 504
                 $ticket->save();
505 505
             }
506 506
         }
@@ -531,7 +531,7 @@  discard block
 block discarded – undo
531 531
                 && $update_ticket
532 532
             ) {
533 533
                 $ticket = $this->ticket();
534
-                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:" . __LINE__ . ')');
534
+                $ticket->decreaseReserved(1, true, "REG: {$this->ID()} (ln:".__LINE__.')');
535 535
             }
536 536
         }
537 537
     }
@@ -1205,7 +1205,7 @@  discard block
 block discarded – undo
1205 1205
                     : '';
1206 1206
                 break;
1207 1207
         }
1208
-        return $icon . $status[ $this->status_ID() ];
1208
+        return $icon.$status[$this->status_ID()];
1209 1209
     }
1210 1210
 
1211 1211
 
@@ -1417,7 +1417,7 @@  discard block
 block discarded – undo
1417 1417
             return false;
1418 1418
         }
1419 1419
         // is there a datetime ticket that matches this dtt_ID?
1420
-        if (! (EEM_Datetime_Ticket::instance()->exists(
1420
+        if ( ! (EEM_Datetime_Ticket::instance()->exists(
1421 1421
             array(
1422 1422
                 array(
1423 1423
                     'TKT_ID' => $this->get('TKT_ID'),
@@ -1448,7 +1448,7 @@  discard block
 block discarded – undo
1448 1448
     {
1449 1449
         $DTT_ID = EEM_Datetime::instance()->ensure_is_ID($DTT_OR_ID);
1450 1450
 
1451
-        if (! $DTT_ID) {
1451
+        if ( ! $DTT_ID) {
1452 1452
             return false;
1453 1453
         }
1454 1454
 
@@ -1456,7 +1456,7 @@  discard block
 block discarded – undo
1456 1456
 
1457 1457
         // if max uses is not set or equals infinity then return true cause its not a factor for whether user can
1458 1458
         // check-in or not.
1459
-        if (! $max_uses || $max_uses === EE_INF) {
1459
+        if ( ! $max_uses || $max_uses === EE_INF) {
1460 1460
             return true;
1461 1461
         }
1462 1462
 
@@ -1516,7 +1516,7 @@  discard block
 block discarded – undo
1516 1516
             $datetime = $this->get_latest_related_datetime();
1517 1517
             $DTT_ID = $datetime instanceof EE_Datetime ? $datetime->ID() : 0;
1518 1518
             // verify the registration can checkin for the given DTT_ID
1519
-        } elseif (! $this->can_checkin($DTT_ID, $verify)) {
1519
+        } elseif ( ! $this->can_checkin($DTT_ID, $verify)) {
1520 1520
             EE_Error::add_error(
1521 1521
                 sprintf(
1522 1522
                     esc_html__(
@@ -1539,7 +1539,7 @@  discard block
 block discarded – undo
1539 1539
         );
1540 1540
         // start by getting the current status so we know what status we'll be changing to.
1541 1541
         $cur_status = $this->check_in_status_for_datetime($DTT_ID, null);
1542
-        $status_to = $status_paths[ $cur_status ];
1542
+        $status_to = $status_paths[$cur_status];
1543 1543
         // database only records true for checked IN or false for checked OUT
1544 1544
         // no record ( null ) means checked in NEVER, but we obviously don't save that
1545 1545
         $new_status = $status_to === EE_Checkin::status_checked_in ? true : false;
@@ -1704,7 +1704,7 @@  discard block
 block discarded – undo
1704 1704
     public function transaction()
1705 1705
     {
1706 1706
         $transaction = $this->get_first_related('Transaction');
1707
-        if (! $transaction instanceof \EE_Transaction) {
1707
+        if ( ! $transaction instanceof \EE_Transaction) {
1708 1708
             throw new EntityNotFoundException('Transaction ID', $this->transaction_ID());
1709 1709
         }
1710 1710
         return $transaction;
@@ -1758,11 +1758,11 @@  discard block
 block discarded – undo
1758 1758
             );
1759 1759
             return;
1760 1760
         }
1761
-        if (! $this->reg_code()) {
1761
+        if ( ! $this->reg_code()) {
1762 1762
             parent::set('REG_code', $REG_code, $use_default);
1763 1763
         } else {
1764 1764
             EE_Error::doing_it_wrong(
1765
-                __CLASS__ . '::' . __FUNCTION__,
1765
+                __CLASS__.'::'.__FUNCTION__,
1766 1766
                 esc_html__('Can not change a registration REG_code once it has been set.', 'event_espresso'),
1767 1767
                 '4.6.0'
1768 1768
             );
@@ -1913,7 +1913,7 @@  discard block
 block discarded – undo
1913 1913
                 break;
1914 1914
             }
1915 1915
         }
1916
-        if (! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1916
+        if ( ! ($line_item instanceof \EE_Line_Item && $line_item->OBJ_type() === 'Ticket')) {
1917 1917
             throw new EntityNotFoundException('Line Item Ticket ID', $ticket->ID());
1918 1918
         }
1919 1919
         return $line_item;
@@ -2086,7 +2086,7 @@  discard block
 block discarded – undo
2086 2086
     public function name()
2087 2087
     {
2088 2088
         $attendee = $this->attendee();
2089
-        if($attendee instanceof EE_Attendee){
2089
+        if ($attendee instanceof EE_Attendee) {
2090 2090
             $attendee_name = $attendee->full_name();
2091 2091
         } else {
2092 2092
             $attendee_name = esc_html__('Unknown', 'event_espresso');
Please login to merge, or discard this patch.